Python豆知识
1."import this"だけじゃない
Hello world!
The Zen of Python, by Tim Peters
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!
2. ...
Ellipsis
<class 'ellipsis'>
4352958848
4352958848
True
使い道
# typingとして使う
from typing import Callable
def partial(func: Callable[..., str], *args) -> Callable[..., str]:
# Body
array([[[ 0, 1, 2, 3],
[ 4, 5, 6, 7]],
[[ 8, 9, 10, 11],
[12, 13, 14, 15]]])
array([[ 2, 6],
[10, 14]])
array([[ 2, 6],
[10, 14]])
3. shellのendを真似したいなら...(使わないでください)
__builtins__.end = None
def my_abs(x):
if x > 0:
return x
else:
return -x
end
end
print(my_abs(10))
print(my_abs(-10))
10
10
4. promptを自分で定義する
```python
>>> import sys
>>> sys.ps1
'>>> '
>>> sys.ps2
'... '
>>> sys.ps3
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: module 'sys' has no attribute 'ps3'
>>> sys.ps1 = "海賊王に俺はなる!>>>"
海賊王に俺はなる!>>>sys.ps2 = "肉~"
海賊王に俺はなる!>>>for i in range(2):
肉~ print("サンジ、腹減った")
肉~
サンジ、腹減った
サンジ、腹減った
海賊王に俺はなる!>>>
14
''
'b'
'a'
{}
6. リストを結合する
[1, 2, 3, 4, 5, 6]
[1, 2, 3, 4, 5, 6]
[1, 2, 3, 4, 5, 6]
7. [-5, 256]
False
True
CPythonでは、[-5, 256]間の整数は事前に定義されたオブジェクト
他の数字と違う
8. 文字列のintern
True
False
9. dict()と{}
112 ns ± 4.2 ns per loop (mean ± std. dev. of 5 runs, 1000000 loops each)
21.6 ns ± 1.42 ns per loop (mean ± std. dev. of 5 runs, 1000000 loops each)
{}
はdict()
より早い
1 0 BUILD_MAP 0
2 RETURN_VALUE
1 0 LOAD_NAME 0 (dict)
2 CALL_FUNCTION 0
4 RETURN_VALUE
10."e"と"е"
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-50-6b554beb183e> in <module>
1 valuе = 12
----> 2 print(value)
NameError: name 'value' is not defined
原因は上の"valuе"の"е"は普通の"e"ではない
101
1077
使い道?
いたずら!
11. "site"
['/Users/maozhongfu/GitHub/Python',
'/Users/maozhongfu/.vscode/extensions/ms-python.python-2020.10.332292344/pythonFiles',
'/Users/maozhongfu/.vscode/extensions/ms-python.python-2020.10.332292344/pythonFiles/lib/python',
'/Library/Frameworks/Python.framework/Versions/3.8/lib/python38.zip',
'/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8',
'/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/lib-dynload',
'',
'/Users/maozhongfu/Library/Python/3.8/lib/python/site-packages',
'/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages',
'/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/aeosa',
'/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/IPython/extensions',
'/Users/maozhongfu/.ipython',
'/Users/maozhongfu/.vscode/extensions/ms-python.python-2020.10.332292344/pythonFiles/vscode_datascience_helpers/dataframes']
sys.path = [
'/Users/maozhongfu/GitHub/Python',
'/Users/maozhongfu/.vscode/extensions/ms-python.python-2020.10.332292344/pythonFiles',
'/Users/maozhongfu/.vscode/extensions/ms-python.python-2020.10.332292344/pythonFiles/lib/python',
'/Library/Frameworks/Python.framework/Versions/3.8/lib/python38.zip',
'/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8',
'/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/lib-dynload',
'/Users/maozhongfu/Library/Python/3.8/lib/python/site-packages',
'/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages',
'/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/aeosa',
]
USER_BASE: '/Users/maozhongfu/Library/Python/3.8' (exists)
USER_SITE: '/Users/maozhongfu/Library/Python/3.8/lib/python/site-packages' (exists)
ENABLE_USER_SITE: True
12. http server
cd <path> # シェアしたいフォルダまで移動
ipconfig # 自分のipを把握他人に教える
python3 -m http.server <port number> # port numberでサーバーを立ち上げる
# その後 "http://<ip adress>:<port number>"でアクセルできる
13. pydoc
14. ":=" (python3.8以上)
if..else..
お酒を飲めてもいい
お酒を飲めてもいい
while
file = open("demo.txt", "r")
while True:
line = file.readline()
if not line:
break
print(line.strip())
comprehension
scores = [22,54,75,89]
valid_scores = [
longFunction(n)
for n in scores
if longFunction(n) # longFunctionは2回実行される
]
15. decorator
パラメータありの関数のdecorator
def say_hello(country:str = None):
def wrapper(func):
def deco(*args, **kwargs):
if country == "China":
print("你好!")
elif country == "Japan":
print("こんにちは!")
else:
print("Winter is Coming!")
func(*args, **kwargs)
return deco
return wrapper
@say_hello("China")
def 诸葛孔明():
...
@say_hello("Japan")
def 桃太郎():
pass
@say_hello()
def JonSnow():
pass
你好!
こんにちは!
Winter is Coming!
パラメータ無しのクラスdecorator
class logger(object):
def __init__(self, func):
self._func = func
def __call__(self, *args, **kwargs):
print(f"[INFO]: function {self._func.__name__} is running")
return self._func(*args, **kwargs)
@logger
def say(something):
print(f"say {something}")
say("Hello")
[INFO]: function say is running
say Hello
パラメータありのクラスdecorator
class logger(object):
def __init__(self, level="INFO"):
self._level = level
def __call__(self, func):
def wrapper(*args, **kwargs):
print(f"[{self._level}]: function {func.__name__} is running")
func(*args, **kwargs)
return wrapper
@logger(level="DEBUG")
def say(something):
print(f"say {something}")
say("Hello")
[DEBUG]: function say is running
say Hello
クラスのdecorator
def singleton(cls):
_instance = {}
def inner():
if cls not in _instance:
_instance[cls] = cls()
return _instance[cls]
return inner
@singleton
class Test(object):
def __init__(self):
pass
foo = Test()
bar = Test()
print(id(foo) == id(bar))
True
16.lru_cache
from functools import lru_cache
@lru_cache()
def fib_with_cache(n):
if n < 2:
return n
return fib_with_cache(n - 2) + fib_with_cache(n - 1)
CPU times: user 2.65 ms, sys: 35 µs, total: 2.69 ms
Wall time: 2.75 ms
6765
CPU times: user 1.35 ms, sys: 8 µs, total: 1.35 ms
Wall time: 1.38 ms
4224696333392304878706725602341482782579852840250681098010280137314308584370130707224123599639141511088446087538909603607640194711643596029271983312598737326253555802606991585915229492453904998722256795316982874482472992263901833716778060607011615497886719879858311468870876264597369086722884023654422295243347964480139515349562972087652656069529806499841977448720155612802665404554171717881930324025204312082516817125
17.print to file
hello world
18. for..else.., try..else..
def check_item(source:list, target:str):
for item in source:
if item == target:
print("あった!")
break
else:
print("無かった")
source=["Apple", "Huawei", "Xiaomi"]
あった!
無かった
def test_try_else(attr1 = None):
try:
if attr1:
pass
else:
raise
except:
print("Exception occurred...")
else:
print("No Exception occurred...")
Exception occurred...
No Exception occurred...
19.numba
Collecting numba
Downloading numba-0.51.2-cp38-cp38-macosx_10_14_x86_64.whl (2.2 MB)
[K |████████████████████████████████| 2.2 MB 3.8 MB/s
[?25hCollecting llvmlite<0.35,>=0.34.0.dev0
Downloading llvmlite-0.34.0-cp38-cp38-macosx_10_9_x86_64.whl (18.4 MB)
[K |████████████████████████████████| 18.4 MB 19.5 MB/s
[?25hRequirement already satisfied: setuptools in /Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages (from numba) (50.3.2)
Requirement already satisfied: numpy>=1.15 in /Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages (from numba) (1.19.0)
Installing collected packages: llvmlite, numba
Successfully installed llvmlite-0.34.0 numba-0.51.2
import numba as nb
@nb.jit()
def nb_sum(a):
Sum = 0
for i in range(len(a)):
Sum += a[i]
return Sum
def py_sum(a):
Sum = 0
for i in range(len(a)):
Sum += a[i]
return Sum
import numpy as np
a = np.linspace(0,100,100)
%timeit np.sum(a) # numpy
%timeit sum(a) # pythonのsum関数
%timeit nb_sum(a) # numba
%timeit py_sum(a) # 上のやつ
4.1 µs ± 106 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
17.8 µs ± 193 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
372 ns ± 0.67 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
23.8 µs ± 475 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
20. 里程標日付
- Python 1.0 1994
- Python 2.Xの最期 2020/1/1
- Python 3.0 2008/12/3
21.PEP
- PEP 0: 全てのPEPのIndex
- PEP 1: PEPの目標とガイドライン
- PEP 8: スタイルガイド
- PEP 20: Pythonの禅
- PEP 404: 永遠に来ないPython 2.8
- PEP 484: 型ヒント
- PEP 498: f-string
22.CPythonだけじゃない
- Stackless Python
- Jython -> もう死んだ同然
- IronPython
- PyPy
- MicroPython
- Cython
23.拡張子
.py
-> ソースコード.pyc
-> バイトコンパイル済ファイル.pyo
-> 最適化(-O)されたバイトコード.pyd
-> PythonスクリプトからWindows DLLを作ったもの.py3
-> Python3 スクリプト.pyw
-> Windows用のPythonスクリプトファイル,pythonw.exe
で実行.pyx
-> ソースをC/C++へコンバートしたもの
24. Guido van Rossum(Python BDFL)
25.Position-only parameters(>=python 3.8)
[0;31mSignature:[0m [0mmath[0m[0;34m.[0m[0msin[0m[0;34m([0m[0mx[0m[0;34m,[0m [0;34m/[0m[0;34m)[0m[0;34m[0m[0;34m[0m[0m
[0;31mDocstring:[0m Return the sine of x (measured in radians).
[0;31mType:[0m builtin_function_or_method
'/'前のパラメータは位置限定で、キーワードで指定するのはできない
'*'以後のパラメータはキーワード限定
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-3-5993719a7116> in <module>
1 import math
2
----> 3 math.sin(x=1)
TypeError: sin() takes no keyword arguments
26.typing
from typing import Tuple
RGB = Tuple[int, int, int]
HSL = Tuple[float, float, float]
def rgb_to_hsl(color: RGB) -> HSL:
def hsl_complement(color: HSL) -> HSL:
def hsl_to_rgb(color: HSL) -> RGB:
from typing import NamedTuple, Union
class RGB(NamedTuple):
red: int
green: int
blue: int
def hex_to_rgb2(hx_int: Union[int, str]) -> RGB:
from typing import Optional, Tuple
def polydice(n: Optional[int] = None, sides: int = 6) -> Tuple[int, ...]:
if n is None:
n = 2 if sides == 6 else 1
return tuple(random.randint(1, sides) for _ in range(n))
27.Exeを作る
exeファイルを作るにはいくつかのツールがある * PyInstaller -> Windows, MacOS対応, おすすめ * BriefCase -> Windows, MacOS対応 * py2exe * cx_freeze * Nuitka -> exeファイルを作る前にまずCコードに変換する
Windows
Collecting pyinstaller
Downloading pyinstaller-4.1.tar.gz (3.5 MB)
[K |████████████████████████████████| 3.5 MB 7.8 MB/s
[?25h Installing build dependencies ... [?25ldone
[?25h Getting requirements to build wheel ... [?25ldone
[?25h Preparing wheel metadata ... [?25ldone
[?25hCollecting pyinstaller-hooks-contrib>=2020.6
Downloading pyinstaller_hooks_contrib-2020.10-py2.py3-none-any.whl (166 kB)
[K |████████████████████████████████| 166 kB 14.2 MB/s
[?25hCollecting macholib>=1.8; sys_platform == "darwin"
Downloading macholib-1.14-py2.py3-none-any.whl (37 kB)
Collecting altgraph
Downloading altgraph-0.17-py2.py3-none-any.whl (21 kB)
Requirement already satisfied: setuptools in /Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages (from pyinstaller) (50.3.2)
Building wheels for collected packages: pyinstaller
Building wheel for pyinstaller (PEP 517) ... [?25ldone
[?25h Created wheel for pyinstaller: filename=pyinstaller-4.1-py3-none-any.whl size=2790248 sha256=b79a93485851db867f7f2f885330faa8e3d832ce0179768b80bc1b2f16e76d2f
Stored in directory: /Users/maozhongfu/Library/Caches/pip/wheels/ae/7a/1e/e42202ec16f036e6c25592c6bc63d3c26e6a6addd6a25f053a
Successfully built pyinstaller
Installing collected packages: pyinstaller-hooks-contrib, altgraph, macholib, pyinstaller
Successfully installed altgraph-0.17 macholib-1.14 pyinstaller-4.1 pyinstaller-hooks-contrib-2020.10
commandline
%%writefile pysearch.py
import argparse
import pathlib
def search_folder(path, extension, file_size=None):
"""
Search folder for files
"""
folder = pathlib.Path(path)
files = list(folder.rglob(f'*.{extension}'))
if not files:
print(f'No files found with {extension=}')
return
if file_size is not None:
files = [f for f in files
if f.stat().st_size > file_size]
print(f'{len(files)} *.{extension} files found:')
for file_path in files:
print(file_path)
def main():
parser = argparse.ArgumentParser(
'PySearch',
description='PySearch - The Python Powered File Searcher')
parser.add_argument('-p', '--path',
help='The path to search for files',
required=True,
dest='path')
parser.add_argument('-e', '--ext',
help='The extension to search for',
required=True,
dest='extension')
parser.add_argument('-s', '--size',
help='The file size to filter on in bytes',
type=int,
dest='size',
default=None)
args = parser.parse_args()
search_folder(args.path, args.extension, args.size)
if __name__ == '__main__':
main()
Writing pysearch.py
GUI
%%writefile image_viewer.py
import wx
class ImagePanel(wx.Panel):
def __init__(self, parent, image_size):
super().__init__(parent)
self.max_size = 240
img = wx.Image(*image_size)
self.image_ctrl = wx.StaticBitmap(self,
bitmap=wx.Bitmap(img))
browse_btn = wx.Button(self, label='Browse')
browse_btn.Bind(wx.EVT_BUTTON, self.on_browse)
self.photo_txt = wx.TextCtrl(self, size=(200, -1))
main_sizer = wx.BoxSizer(wx.VERTICAL)
hsizer = wx.BoxSizer(wx.HORIZONTAL)
main_sizer.Add(self.image_ctrl, 0, wx.ALL, 5)
hsizer.Add(browse_btn, 0, wx.ALL, 5)
hsizer.Add(self.photo_txt, 0, wx.ALL, 5)
main_sizer.Add(hsizer, 0, wx.ALL, 5)
self.SetSizer(main_sizer)
main_sizer.Fit(parent)
self.Layout()
def on_browse(self, event):
"""
Browse for an image file
@param event: The event object
"""
wildcard = "JPEG files (*.jpg)|*.jpg"
with wx.FileDialog(None, "Choose a file",
wildcard=wildcard,
style=wx.ID_OPEN) as dialog:
if dialog.ShowModal() == wx.ID_OK:
self.photo_txt.SetValue(dialog.GetPath())
self.load_image()
def load_image(self):
"""
Load the image and display it to the user
"""
filepath = self.photo_txt.GetValue()
img = wx.Image(filepath, wx.BITMAP_TYPE_ANY)
# scale the image, preserving the aspect ratio
W = img.GetWidth()
H = img.GetHeight()
if W > H:
NewW = self.max_size
NewH = self.max_size * H / W
else:
NewH = self.max_size
NewW = self.max_size * W / H
img = img.Scale(NewW,NewH)
self.image_ctrl.SetBitmap(wx.Bitmap(img))
self.Refresh()
class MainFrame(wx.Frame):
def __init__(self):
super().__init__(None, title='Image Viewer')
panel = ImagePanel(self, image_size=(240,240))
self.Show()
if __name__ == '__main__':
app = wx.App(redirect=False)
frame = MainFrame()
app.MainLoop()
Mac
Macの場合は、選択肢は以下となる * PyInstaller * Briefcase * py2app
27. "_"と"__"
_
: ループ、unpackingなどに利用されない臨時変数_var
: 直接アクセスしたくない__var
: privatevar_
: keywordとのコンフリクトを回避__var__
: magic functions