北冥神功は、道教の荘子『逍遥游』に由来しています。その主旨は以下のポイントに全て集約されています:
「世の人々は功を練るとき、皆自ら云門から少商に至ると云うが、我が逍遥派はその道を逆に行き、自ら少商から云門に至る。親指と人が接触し、彼の内力は即ち我が身に入り、云門などの諸穴に蓄えられる。しかし、敵の内力が我を上回るならば、海水が逆流して江河に入ることになり、危険この上ない。慎重に、慎重に。」
北冥神功の修行心法から見ると、これは普通の内功修行者の筋脈の行き方とは全く逆です。したがって、北冥神功は海納百川の機能を持ち、全ての内功を吸収することができます。そして、この吸収には全く副作用がなく、他人の内力を同化することもできます。
iterable 技術
▍1、数字のシーケンスを作成する(0 から 10 まで、間隔は 2)
>>> range(0,10,2)
[0, 2, 4, 6, 8]
▍2、一連の数字の合計を求める(0 から 10 まで、間隔は 2)
>>> l = range(0,10,2)
>>> sum(l)
20
▍3、シーケンス内の任意の要素が True であるかを確認する
>>> any(a % 2 for a in range(0,10,2))
True
▍4、シーケンス内の全ての要素が True であるかを確認する
>>> all(a % 2 for a in range(0,10,2))
True
▍5、一連の数字シーケンスの累積和を求める
>>> import numpy as np
>>> res = list(np.cumsum(range(0,10,2)))
>>> res
[ 0, 2, 6, 12, 20]
▍6、各 iterable にインデックスを追加してタプルを構築する
>>> a = ['Hello', 'world', '!']
>>> list(enumerate(a))
[(0, 'Hello'), (1, 'world'), (2, '!')]
▍7、iterable を単一の文字列に結合する
>>> a = ["python","really", "rocks"]
>>> " ".join(a)
'python really rocks'
▍8、二つの iterable を組み合わせるか、pivot ネストされた iterables を組み合わせる
# 二つのiterablesを組み合わせる
>>> a = [1, 2, 3]
>>> b = ['a', 'b', 'c']
>>> z = zip(a, b)
>>> z
[(1, 'a'), (2, 'b'), (3, 'c')]
# タプルのリストをピボットする
>>> zip(*z)
[(1, 2, 3), ('a', 'b', 'c')]
▍9、iterables から最小値 / 最大値を取得する(特定の機能を持つ / 持たない)
# iterableから最大値を取得する
>>> a = [1, 2, -3]
>>> max(a)
2
# iterableから最小値を取得する
>>> min(a)
1
# min/maxはkey値を持ち、関数を適用して最大値を取得できる
>>> max(a,key=abs)
3
▍10、iterable をソートする(「compare」関数でソート可能)
>>> a = [1, 2, -3]
>>> sorted(a)
[-3, 1, 2]
>>> sorted(a,key=abs)
[1, 2, -3]
▍11、単一の文字列をリストに分割する
>>> s = "a,b,c"
>>> s.split(",")
["a", "b", "c"]
▍12、重複した数字を含むリストを初期化する
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
▍13、二つの辞書をマージ / 挿入する
>>> a = {"a":1, "b":1}
>>> b = {"b":2, "c":1}
>>> a.update(b)
>>> a
{"a":1, "b":2, "c":1}
▍14、iterables のスライスに名前を付けて保存する
# スライスに名前を付ける (slice(start, end, step))
>>> a = [0, 1, 2, 3, 4, 5]
>>> LASTTHREE = slice(-3, None)
>>> LASTTHREE
slice(-3, None, None)
>>> a[LASTTHREE]
[3, 4, 5]
▍15、リスト内の項目のインデックスを見つける
>>> a = ["foo", "bar", "baz"]
>>> a.index("bar")
1
▍16、iterables 内の最小 / 最大項目のインデックスを見つける
>>> a = [2, 3, 1]
>>> min(enumerate(a),key=lambda x: x[1])[0]
2
▍17、iterables の k 個の要素を回転させる
>>> a = [1, 2, 3, 4]
>>> k = 2
>>> a[-2:] + a[:-2]
[3, 4, 1, 2]
▍18、文字列の末尾 / 開始 / 両端の無用な文字を削除する
>>> name = "//George//"
>>> name.strip("/")
'George'
>>> name.rstrip("/")
'//George'
>>> name.lstrip("/")
'George//'
▍19、iterables の順序を逆にする(文字列、リストなど)
# 文字列を逆にする
>>> s = "abc"
>>> s[::-1]
"cba"
# リストを逆にする
>>> l = ["a", "b", "c"]
>>> l[::-1]
["c", "b", "a"]
branching 技術
▍20、複数のショートカット
>>> n = 10
>>> 1 < n < 20
True
▍21、For-else 構造は、何かを検索して見つけたときに非常に便利です
for i in mylist:
if i == theflag:
break
process(i)
else:
raise ValueError("リスト引数に終端フラグがありません。")
▍22、三項演算子
>>> "Python ROCK" if True else " I AM GRUMPY"
"Python ROCK"
▍23、Try-catch-else 構造
try:
foo()
except Exception:
print("例外が発生しました")
else:
print("例外は発生しませんでした")
finally:
print("常にここに到達します")
▍24、While-else 構造
i = 5
while i > 1:
print("Whil-ing away!")
i -= 1
if i == 3:
break
else:
print("終了しました!")
comprehensions(推導式)技術
▍25、リスト推導式
>>> m = [x ** 2 for x in range(5)]
>>> m
[0, 1, 4, 9, 16]
▍26、セット推導式
>>> m = {x ** 2 for x in range(5)}
>>> m
{0, 1, 4, 9, 16}
▍27、辞書推導式
>>> m = {x: x ** 2 for x in range(5)}
>>> m
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
▍28、ジェネレータ推導式
# ジェネレータ推導式はリスト推導式の遅延バージョンです。
>>> m = (x ** 2 for x in range(5))
>>> m
<generator object <genexpr> at 0x108efe408>
>>> list(m)
[0, 1, 4, 9, 16]
>>> m = (x ** 2 for x in range(5))
>>> next(m)
0
>>> list(m)
[1, 4, 9, 16]
▍29、現在の値と過去の値を使用したリスト推導
>>> a = [1, 2, 4,2]
>>> [y - x for x,y in zip(a,a[1:])]
[1, 2, -2]
unpacking 技術
▍30、iterable から変数を解凍する
# すべてのiterables(タプル、リストなど)を解凍できます
>>> a, b, c = 1, 2, 3
>>> a, b, c
(1, 2, 3)
>>> a, b, c = [1, 2, 3]
>>> a, b, c
(1, 2, 3)
▍31、変数の値を交換する
>>> a, b = 1, 2
>>> a, b = b, a
>>> a, b
(2, 1)
▍32、すべての要素を指定せずに iterable から変数を解凍する
>>> a, *b, c = [1, 2, 3, 4, 5]
>>> a
1
>>> b
[2, 3, 4]
>>> c
5
▍33、スプラット演算子を使用して変数を解凍する
>>> def test(x, y, z):
>>> print(x, y, z)
>>> res = test(*[10, 20, 30])
10 20 30
>>> res = test(**{'x': 1, 'y': 2, 'z': 3} )
10 20 30
view raw
Itertools 技術
▍34、iterables をフラット化する
>>> a = [[1, 2], [3, 4], [5, 6]]
>>> list(itertools.chain.from_iterable(a))
[1, 2, 3, 4, 5, 6]
▍35、iterables からデカルト積を作成する
>>> for p in itertools.product([1, 2, 3], [4, 5]):
>>> print(''.join(str(x) for x in p))
(1, 4)
(1, 5)
(2, 4)
(2, 5)
(3, 4)
(3, 5)
▍36、iterable から順列を作成する
>>> for p in itertools.permutations([1, 2, 3, 4]):
>>> print(''.join(str(x) for x in p))
123
132
213
231
312
321
▍37、iterable から n-gram を作成する
>>> from itertools import islice
>>> def n_grams(a, n):
... z = (islice(a, i, None) for i in range(n))
... return zip(*z)
...
>>> a = [1, 2, 3, 4, 5, 6]
>>> n_grams(a, 3)
[(1, 2, 3), (2, 3, 4), (3, 4, 5), (4, 5, 6)]
>>> n_grams(a, 2)
[(1, 2), (2, 3), (3, 4), (4, 5), (5, 6)]
>>> n_grams(a, 4)
[(1, 2, 3, 4), (2, 3, 4, 5), (3, 4, 5, 6)]
▍38、二つのイテレータを組み合わせるためにパディングを使用するか、ネストされた iterables をパディングする
>>> import itertools as it
>>> x = [1, 2, 3, 4, 5]
>>> y = ['a', 'b', 'c']
>>> list(zip(x, y))
[(1, 'a'), (2, 'b'), (3, 'c')]
>>> list(it.zip_longest(x, y))
[(1, 'a'), (2, 'b'), (3, 'c'), (4, None), (5, None)]
▍39、iterable n から k 個の組み合わせを作成する
>>> import itertools
>>> bills = [20, 20, 20, 10, 10, 10, 10, 10, 5, 5, 1, 1, 1, 1, 1]
>>> list(itertools.combinations(bills, 3))
[(20, 20, 20), (20, 20, 10), (20, 20, 10), ... ]
▍40、与えられた関数の下で累積結果を生成する
>>> import itertools
>>> list(itertools.accumulate([9, 21, 17, 5, 11, 12, 2, 6], min))
[9, 9, 9, 5, 5, 5, 2, 2]
▍41、iterable から要素を返すイテレータを作成する(述語が True である限り)
>>> import itertools
>>> itertools.takewhile(lambda x: x < 3, [0, 1, 2, 3, 4])
[0, 1, 2]
>>> it.dropwhile(lambda x: x < 3, [0, 1, 2, 3, 4])
[3, 4]
▍42、iterable から要素をフィルタリングするイテレータを作成する(述語が False である要素のみを返す)
>>> import itertools
# 偽の値のみを保持する
>>> list(itertools.filterfalse(bool, [None, False, 1, 0, 10]))
[None, False, 0]
▍43、iterable から得られたパラメータを使用して関数を計算するイテレータを作成する
>>> import itertools
>>> import operator
>>> a = [(2, 6), (8, 4), (7, 3)]
>>> list(itertools.starmap(operator.mul, a))
[12, 32, 21]
collections 技術
▍44、基本操作を設定する
>>> A = {1, 2, 3, 3}
>>> A
set([1, 2, 3])
>>> B = {3, 4, 5, 6, 7}
>>> B
set([3, 4, 5, 6, 7])
>>> A | B
set([1, 2, 3, 4, 5, 6, 7])
>>> A & B
set([3])
>>> A - B
set([1, 2])
>>> B - A
set([4, 5, 6, 7])
>>> A ^ B
set([1, 2, 4, 5, 6, 7])
>>> (A ^ B) == ((A - B) | (B - A))
True
▍45、カウンタデータ構造(無秩序な集合で、要素は辞書のキーとして保存され、そのカウントは辞書の値として保存される)
import collections
>>> A = collections.Counter([1, 1, 2, 2, 3, 3, 3, 3, 4, 5, 6, 7])
>>> A
Counter({3: 4, 1: 2, 2: 2, 4: 1, 5: 1, 6: 1, 7: 1})
>>> A.most_common(1)
[(3, 4)]
>>> A.most_common(3)
[(3, 4), (1, 2), (2, 2)]
▍46、デフォルト辞書構造(辞書のサブクラスで、存在しないキーにアクセスするとデフォルト値を取得する)
>>> import collections
>>> m = collections.defaultdict(int)
>>> m['a']
0
>>> m = collections.defaultdict(str)
>>> m['a']
''
>>> m['b'] += 'a'
>>> m['b']
'a'
>>> m = collections.defaultdict(lambda: '[default value]')
>>> m['a']
'[default value]'
>>> m['b']
'[default value]'
>>> m = collections.defaultdict(list)
>>> m['a']
[]
▍47、順序付き dict 構造(順序付き辞書のサブクラスを保持する)
>>> from collections import OrderedDict
>>> d = OrderedDict.fromkeys('abcde')
>>> d.move_to_end('b')
>>> ''.join(d.keys())
'acdeb'
>>> d.move_to_end('b', last=False)
>>> ''.join(d.keys())
'bacde'
▍48、Deques 構造(Deques はスタックとキューの一般化)
>>> import collection
>>> Q = collections.deque()
>>> Q.append(1)
>>> Q.appendleft(2)
>>> Q.extend([3, 4])
>>> Q.extendleft([5, 6])
>>> Q
deque([6, 5, 2, 1, 3, 4])
>>> Q.pop()
4
>>> Q.popleft()
6
>>> Q
deque([5, 2, 1, 3])
>>> Q.rotate(3)
>>> Q
deque([2, 1, 3, 5])
>>> Q.rotate(-3)
>>> Q
deque([5, 2, 1, 3])
>>> last_three = collections.deque(maxlen=3)
>>> for i in range(4):
... last_three.append(i)
... print ', '.join(str(x) for x in last_three)
...
0
0, 1
0, 1, 2
1, 2, 3
2, 3, 4
▍49、名前付きタプル構造(フィールドに属性アクセスを通じてアクセスできるクラスタプルオブジェクトを作成する)
>>> import collections
>>> Point = collections.namedtuple('Point', ['x', 'y'])
>>> p = Point(x=1.0, y=2.0)
>>> p
Point(x=1.0, y=2.0)
>>> p.x
1.0
>>> p.y
2.0
▍50、辞書を使用してスイッチを保存する
>>> func_dict = {'sum': lambda x, y: x + y, 'subtract': lambda x, y: x - y}
>>> func_dict['sum'](9,3)
12
>>> func_dict['subtract'](9,3)
6
▍51、データクラス構造
>>> from dataclasses import dataclass
>>> @dataclass
>>> class DataClassCard:
>>> rank: str
>>> suit: str
>>> queen_of_hearts = DataClassCard('Q', 'Hearts')
>>> queen_of_hearts.rank
'Q'
>>> queen_of_hearts
DataClassCard(rank='Q', suit='Hearts')
>>> queen_of_hearts == DataClassCard('Q', 'Hearts')
True
その他の技術
▍52、UUID を生成する
# これはランダム化された
#128ビットの番号を作成し、ほぼ確実にユニークです。
# 実際、生成可能なUUIDは2¹²²以上です。
# それは5の未満の数(または5,000,000,000,000,000,000,000,000,000,000,000,000)です。
>>> import uuid
>>> user_id = uuid.uuid4()
>>> user_id
UUID('7c2faedd-805a-478e-bd6a-7b26210425c7')
▍53、LRU キャッシュを使用してメモ化する
import functools
@functools.lru_cache(maxsize=128)
def fibonacci(n):
if n == 0:
return 0
elif n == 1:
return 1
return fibonacci(n - 1) + fibonacci(n - 2)
▍54、式の抑制
>>> from contextlib import suppress
>>> with contextlib.suppress(ZeroDivisionError):
>>> 10/0
# 例外は発生しません
▍55、設定と解除が必要な場合にコンテキストマネージャを作成する
class FileManager:
def __init__(self, filename):
self.filename = filename
self.file = None
def __enter__(self):
self.file = open(self.filename, 'r')
return self.file
def __exit__(self, exc_type, exc_val, exc_tb):
if self.file:
self.file.close()
# コンテキストマネージャを使用してファイルを読み取る
with FileManager('example.txt') as file:
for line in file:
print(line)
▍56、ファイルパスを扱うための優雅な方法(3.4 以上)
>>> from pathlib import Path
>>> data_folder = Path("source_data/text_files/)
# パス計算とメタデータ
>>> file_to_open = data_folder / "raw_data.txt"
>>> file_to_open.name
"raw_data.txt"
>>> file_to_open.suffix
"txt"
>>>file_to_open.stem
"raw_data"
# ファイル関数
>>> f = open(file_to_open)
>>> f.read()
# ファイルの内容
>>> file_to_open.exists()
True
▍57、標準演算子をクラスの関数として実装する
@staticmethod
def add(x, y):
return x + y
@staticmethod
def subtract(x, y):
return x - y
@staticmethod
def multiply(x, y):
return x * y
@staticmethod
def divide(x, y):
return x / y
▍58、関心事を分離するためにデコレータを作成する
>>>from functools import wraps
>>>def add_sandwich(wrapped):
>>> @wraps(wrapped)
>>> def wrapper(*args, **kwargs):
>>> return wrapped(*args, **kwargs) + ' sandwich'
>>> return wrapper
>>>@add_sandwich
>>>def ham():
>>> return 'ham'
>>>ham()
'ham sandwich'
▍59、yield を使用してシンプルなイテレータを作成する
>>> def foo(lst):
>>> for x in lst:
>>> yield x
>>> yield x*2
>>> a = [1, 3]
>>> list(foo(a))
[1, 2, 3, 6]
▍60、yield from の使用例とトリック
def numbers():
yield from range(1, 4)
def letters():
yield from ('A', 'B', 'C')
def combine():
yield from numbers()
yield from letters()
for value in combine():
print(value)
# 出力結果:1 2 3 A B C
彩蛋
▍61、反重力
import antigravity
antigravity.fly()
▍62、Python の禅
>>> import this
The Zen of Python, by Tim Peters
美しさは醜さよりも優れています。
明示的であることは暗黙的であることよりも優れています。
シンプルであることは複雑であることよりも優れています。
複雑であることは込み入ったことよりも優れています。
平坦であることはネストされたことよりも優れています。
まばらであることは密であることよりも優れています。
可読性は重要です。
特別なケースはルールを破るほど特別ではありません。
実用性は純粋さに勝ります。
エラーは決して静かに通過すべきではありません。
明示的に静かにされない限り。
曖昧さに直面したときは、推測する誘惑を拒否してください。
それを行う明らかに一つの方法があるべきです、そしてそれは好ましくも唯一の方法です。
その方法は最初は明らかでないかもしれませんが、オランダ人でない限り。
今は決してより良いです。
決してはしばしば「正しい」今よりも良いです。
実装が説明するのが難しい場合、それは悪いアイデアです。
実装が説明するのが簡単な場合、それは良いアイデアかもしれません。
名前空間は素晴らしいアイデアです、もっとそれを行いましょう!