Probably the most unhelpful Python implementation method on Qiita

Introduction

Python is currently the most desired language to learn. It ranges from heavy developers to light office computing. Probably because I've heard and heard that "You can do XX with Python". In this article, I will mainly introduce and develop such Python from scratch.

OS Sentei

The best operating system for Python development is Windows. Simply select some of the target versions from the official Python.org, download and install properly, and you can start everything, so installation coexistence and package management tool with system default and another ver like Mac and Linux There is no need to be aware of. It's easy because the path passes, and even if you put multiple versions at the same time, even the build version can coexist separately.

Processing system

Since Python is a metamorphosis language in the interpreter world, there are multiple processing systems as much as the Qiita page introducing the processing system appears. In addition to calling CPython, the official processing system that is written in C and stores compiled binaries in the cache at runtime,

--ECMAScript-like JIT PyPy --Java Jython --C # IronPython

and so on. Some, like Cython, are for spitting out C extensions. There is also an integrated environment of the ecosystem itself, such as Anaconda. This is because C/C ++ can seamlessly create Python extension structures for various processing systems, but it is better to create these languages ​​with Node, Java, or C #, which are the languages ​​equivalent to the implementation source, as long as they cling to Pytnon. In many cases, it is quick, has high performance, and the development speed does not change so much, and it is very particular to focus on such a processing system. Also, in order not to bind the environment of Python itself, it is ideal to add accessories later with the accessories removed as much as possible. So here I will choose CPython.

Which version

You can check the latest version 3.10.a3 (as of December 2020) by following the official Download → Source code, so download and install the 64-bit msi file at the bottom of this page. If you need an older version for your convenience, you can add it each time, so I don't care about anything. image.png

Install the build environment.

Some Python libraries are provided on the assumption that they will be built in C/C ++. Or the official PreBinary may not work with the latest version of Python at hand. In that case, if you do not have a C/C ++ build environment at hand, an error is inevitable. If you are a Windows user, you can almost say that Microsoft's Visual C ++ system is an option. In MSYS, Pacman raises the hurdle in Arch Linux, so I will exclude it this time. Download and install either Visual Studio or its Build tools from the official. Make sure to set the option so that C ++ is included when installing. There is no doubt if you select one of the items that says C ++. image.png

Fibonacci.

After installing Python for the time being, type `py``` (note that it is not `python```) at the command prompt, and you will see Python's interactive execution environment (called REPL. Is it IDLE for Python? ) Will start up, so try it. First, enter the following and enter.

python


>>> def fibo(N):
...   if (N < 2): return N
...   return fibo(N-1) + fibo(N-2)
...
>>> fibo(50)

It is a function to find the common Fibonacci number. Python is good at mathematics, so I think it can be solved in about 50 minutes.

Yup.

Far from being a moment, it is enough to finish one job by the time the execution is completed.

If you're talking about Python being good at math, you should first look at reality. Since this Fibonacci number can simply create the amount of calculation of $ O (2 ^ n) $, it is often used as a measuring rod to measure the processing power of the language, but Python struggles even to calculate fibo (50). .. It's only natural that if you compile similar code in a programming language as fast as C ++ and run it at 50, you won't get any immediate results.

Seriousness of C ++

If this is C ++, compiling and executing either of the following codes will instantly kill not only fibo (50) but also fibo (100). There is no need to devise so-called memoization. (However, when it comes to fibo (100), the limit of the number of recursion comes first.)

template meta


#include <iostream>

template<int N>
struct fibo {
    static const long long value = fibo<N-2>::value + fibo<N-1>::value;
};

template<>
struct fibo<0> {
    static const long long value = 0;
};

template<>
struct fibo<1> {
    static const long long value = 1;
};

int main() {
    std::cout << fibo<50> << std::endl;
}

constexpr


#include <iostream>

constexpr long long fibo(const long long N) {
    return N < 2 ? N : fibo(N - 1) + fibo(N - 2);
}

int main() {
    std::cout << fibo(50) << std::endl;
}

Both of them finish the calculation at compile time and automatically optimize the waste during recursion, so it takes almost no compile time. One thing to keep in mind is that for the fibo function on the constexpr side, the argument to be set must be set as a constant or literal, and usually when a long long value that is not a constant or its compatible variable value is entered. It takes time after all because it calculates at runtime. Still, the processing speed of C ++ far surpasses that of running Python live.

I want Python to be faster

At least Python has limited execution performance if it remains within the framework of a scripting language, so it is good to ask for the cooperation of a C ++ teacher here. (It is natural to make a memo, but it is omitted because it goes against the purpose of measuring the processing power of the language) We will use the so-called language extension function to increase the power of Python. C ++ teachers have a powerful weapon called pybind11 that can be used to minimize the hassle of creating joints between language extensions. There is no way not to utilize it. [^ 1]

[^ 1]: Oomoto is made so that it can be written in C, but if it is a Raw implementation, it will take more effort and effort to rewrite the project code to a description that will be concessed by Python.

procedure

--Remove cmake from cmake official and install it. You can pass the path in the installer settings. When using the optional items of Visual Studio, it is a little troublesome because it is necessary to read the dedicated bat file for setting. --Place the C ++ code body that executes the function, CMakeLists.txt for build preparation, setup.py and pyproject.toml for pip in the Python environment to recognize in the same folder. You can create any editor tool, but Visual Studio Code is recommended. --Obtain the pybind11 project by `` `git clone``` etc. and put it on the folder. --Each is described as follows.

fibo.cpp


#include <iostream>
#include <pybind11/pybind11.h>

constexpr long long fibo_con(const long N=50) {
  return N < 2 ? N : fibo_con(N-1) + fibo_con(N-2);
}

template<int N>
struct fibo_ten {
  static const long long value = fibo_ten<N-2>::value + fibo_ten<N-1>::value;
};

template<>
struct fibo_ten<0> {
  static const long long value = 0;
};

template<>
struct fibo_ten<1> {
  static const long long value = 1;
};

namespace py = pybind11;

PYBIND11_MODULE(pythoncpp, m) {
    m.doc() = "pybind fibo";
    py::class_<fibo_ten<50>>(m, "fibo_ten", "").def_readonly_static("value", &fibo_ten<50>::value, "");
    m.def("fibo_con", &fibo_con, "", py::arg("N") = 50);
}

CMakeLists.txt


cmake_minimum_required(VERSION 3.4...3.18)
project(pythoncpp)

add_subdirectory(pybind11)
pybind11_add_module(pythoncpp fibo.cpp)

setup.py


#Reference code: https://github.com/pybind/cmake_example/blob/master/setup.py

import os
import sys
import subprocess

from setuptools import setup, Extension
from setuptools.command.build_ext import build_ext

PLAT_TO_CMAKE = {
    "win32": "Win32",
    "win-amd64": "x64",
    "win-arm32": "ARM",
    "win-arm64": "ARM64",
}

class CMakeExtension(Extension):
    def __init__(self, name, sourcedir=""):
        Extension.__init__(self, name, sources=[])
        self.sourcedir = os.path.abspath(sourcedir)

class CMakeBuild(build_ext):
    def build_extension(self, ext):
        extdir = os.path.abspath(os.path.dirname(self.get_ext_fullpath(ext.name)))

        if not extdir.endswith(os.path.sep):
            extdir += os.path.sep

        cfg = "Debug" if self.debug else "Release"

        cmake_generator = os.environ.get("CMAKE_GENERATOR", "")

        cmake_args = [
            "-DCMAKE_LIBRARY_OUTPUT_DIRECTORY={}".format(extdir),
            "-DPYTHON_EXECUTABLE={}".format(sys.executable),
            "-DEXAMPLE_VERSION_INFO={}".format(self.distribution.get_version()),
            "-DCMAKE_BUILD_TYPE={}".format(cfg),
        ]
        build_args = []

        if self.compiler.compiler_type != "msvc":
            if not cmake_generator:
                cmake_args += ["-GNinja"]

        else:
            single_config = any(x in cmake_generator for x in {"NMake", "Ninja"})
            contains_arch = any(x in cmake_generator for x in {"ARM", "ARM64"})

            if not single_config and not contains_arch:
                cmake_args += ["-A", PLAT_TO_CMAKE[self.plat_name]]

            if not single_config:
                cmake_args += [
                    "-DCMAKE_LIBRARY_OUTPUT_DIRECTORY_{}={}".format(cfg.upper(), extdir)
                ]
                build_args += ["--config", cfg]

        if "CMAKE_BUILD_PARALLEL_LEVEL" not in os.environ:
            if hasattr(self, "parallel") and self.parallel:
                build_args += ["-j{}".format(self.parallel)]

        if not os.path.exists(self.build_temp):
            os.makedirs(self.build_temp)

        subprocess.check_call(
            ["cmake", ext.sourcedir] + cmake_args, cwd=self.build_temp
        )
        subprocess.check_call(
            ["cmake", "--build", "."] + build_args, cwd=self.build_temp
        )

setup(
    name="pythoncpp",
    version="0.0.1",
    author="exli3141",
    author_email="[email protected]",
    description="",
    long_description="",
    ext_modules=[CMakeExtension("pythoncpp")],
    cmdclass={"build_ext": CMakeBuild},
    zip_safe=False,
)

pyproject.toml


[build-system]
requires = [
    "setuptools>=42",
    "wheel",
    "pybind11>=2.6.0",
    "ninja; sys_platform != 'win32'",
    "cmake>=3.12",
]

build-backend = "setuptools.build_meta"

--" py -m pip install `` for the folder where you saved the four files.

python


> py -m pip install ./pythoncpp
Processing c:\users\exli3\pythoncpp
  Installing build dependencies ... done
  Getting requirements to build wheel ... done
    Preparing wheel metadata ... done
Building wheels for collected packages: pythoncpp
  Building wheel for pythoncpp (PEP 517) ... done
  Created wheel for pythoncpp: filename=pythoncpp-0.0.1-cp310-cp310-win_amd64.whl size=51389 sha256=a5dfa77623dbd0c68a464e0be2e6a5e2228926e9df0f387c4d9ddeec07ff5c37
  Stored in directory: C:\Users\exli3\AppData\Local\Temp\pip-ephem-wheel-cache-n2m3fx5l\wheels\e0\3f\c8\070c22c6b57aef709405561e758661aa4d276e2da56a8f9556
Successfully built pythoncpp
Installing collected packages: pythoncpp
  Attempting uninstall: pythoncpp
    Found existing installation: pythoncpp 0.0.1
    Uninstalling pythoncpp-0.0.1:
      Successfully uninstalled pythoncpp-0.0.1
Successfully installed pythoncpp-0.0.1

as a result

Now try with IDLE, which was run by typing `` `py``` as before. This time, we will measure the time so that we can compare it.

>>> import pythoncpp
>>> import time
>>> def fibo(N):
...   if N < 2: return N
...   return fibo(N-2) + fibo(N-1)
...
>>> start = time.perf_counter(); pythoncpp.fibo_con(); time.perf_counter() - start
12586269025
55.67761182785034
>>> ...
Target function Value of N Time required(unit:s)
pythoncpp.fibo_con 40 0.4524
pythoncpp.fibo_con 42 1.1970
pythoncpp.fibo_con 50 55.6776
pythoncpp.fibo_ten 50 0.0001316
fibo(In python) 40 21.2826
fibo(In python) 42 55.9794
fibo(In python) 50 (Maybe it will take tens of minutes)

I decided that it would take too much time to calculate 50 by the fibo function defined in Python, so I stopped it. Since the constexpr function simply does not determine the calculation result in the modularization compilation process, it takes the same amount of time as the normal function definition. What is described in the template meta is a natural result because it simply displays the variable containing the calculation result. The ratio of calculation speeds varies depending on what is being calculated, so it cannot be said unconditionally, but it is important to just look at this ** "Python does not remember itself, but C ++ also learns" **. If you try to write the runtime in Python and the logic in C ++, your future Python programming life will be even more competitive.

Does it work with a Python-like environment?

The original way is to create a py file and execute the code, and speaking of the Python environment, you can cut the virtual environment with virtualenv, insert Jupiter Labo to substitute IDLE, and use useful libraries such as Numpy and Pandas. What connects. [^ 3] For the time being, create a virtualenv environment, set up a folder for C ++ logic on the current folder, draw up a library (like cpproject) based on the above 4 files, and put the startup py file in the current ` After doing py -m pip install ./cpproject```, can you check the operation with py /path/to/main.py```? (Change/to \ at the command prompt)

[^ 3]: If you follow this introduction, the famous Python library written here may not be included in some cases, so it is good to prepare for the past ver.

At the end

Perhaps after reading this article to the end, you should be able to install and use Python without any problems.

Python is an indispensable language for C ++ er because it has a build system called meson that replaces CMake implemented in Python, and it is often involved in building other projects, but vice versa. However, it is indispensable because C ++ has the power to compensate for the processing speed that Python lacks.

An article I made to see what you can do with Python

Somehow, when I look at language comparison introductions, Python gives the impression that "you can do math and machine learning, your dreams grow. It's also a big success on the WEB", but in the first place, "programming language" It is irrelevant to appeal "what the programming language can do" to the introduction of. The current implementation is that the machine learning system is logiced in a high performance language such as C ++, and Python is a trigger to operate it. Pythoning at the front of the WEB is not yet ripe and is almost limited to the back end. Compared to PHP, which has many giants such as WordPress and Laravel, and Node, which has a drive mechanism suitable for reverse proxies and speeds up, and Ruby, which has a backbone by Rails etc. in terms of development, Python is initially It was only "there is an environment". However, in the past, Python's web service ratio has also risen, and now it is active in the back end of major services such as Youtube, Dropbox, Instagram, Pinterest. Originally, the back end of the WEB was a battlefield for scripting languages, and it is natural that smartness like Python will be a big weapon. The advantage of Python is that it is a language that can be supported by a group of libraries formed by many scientists who are not specialized in programming because of the size of the vessel regardless of the policy, such as simple descriptiveness and shallow knowledge of programming. If you dare to talk about "what Python can do" in "things", based on those strengths, you can provide strong support for assistance in science, mars, and programmable situations. Moreover, it can be said that it has the potential to overturn the existing WEB scripting language world. [^ 2]

[^ 2]: If you want to see Python active on the web, don't refer to this article.

Another Python

If you want to include Python as programming, you should learn two other languages ​​besides Python. Since this introduction is a specification that matches my favorite language, Jython and IronPython are good choices if you mainly use Java or C #, and there is a lot of choice to supplement PHP and Ruby that can not be followed with Python. Yes. There would be a different approach for Rust and Go.

End of end

Since this article is a start from the beginning, I hope that better articles will be mass-produced.

The end of the end of the end

I didn't make it in time for Advent Calender ...

Recommended Posts

Probably the most unhelpful Python implementation method on Qiita
A simple Python implementation of the k-nearest neighbor method (k-NN)
Memorize the Python commentary on YouTube.
Sakura Use Python on the Internet
Probably the most straightforward introduction to TensorFlow
Download files on the web with Python
[Python] A progress bar on the terminal
Get information on the 100 most influential tech Twitter users in the world with python.
Created a Python wrapper for the Qiita API
Learn the design pattern "Template Method" in Python
Why the Python implementation of ISUCON 5 used Bottle
I tried the least squares method in Python
Python: Try using the UI on Pythonista 3 on iPad
To dynamically replace the next method in python
Learn the design pattern "Factory Method" in Python
Try CIing the pushed python code on GitHub.
Building multiple Python environments on the same system
Introduction to Python with Atom (on the way)
Sound the buzzer using python on Raspberry Pi 3!
At the time of python update on ubuntu
Try implementing the Monte Carlo method in Python
[Modint] Decoding the AtCoder Library ~ Implementation in Python ~
[Python] Seriously think about the M-1 winning method.
A note on the library implementation that explores hyperparameters using Bayesian optimization in Python