Pythonの組み込み型
文字列とバイト列
>>> print(bytes([102, 111, 111])) b'foo' >>> >>> list(b'foo bar') [102, 111, 111, 32, 98, 97, 114] >>> tuple(b'foo bar') (102, 111, 111, 32, 98, 97, 114) >>> >>> type("hoge moji") <class 'str'> >>> type(b"some bytes") <class 'bytes'>
文字列の連結
>>> substrings=['hoge', 'piyo', 'foo', 'bar'] >>> "".join(substrings) 'hogepiyofoobar' >>> ",".join(substrings) 'hoge,piyo,foo,bar'
リストの内包表記
下記のコードだと、C言語では問題なさそうだが、Pythonでは3つの問題がある。
・リストを操作するコードをループごとにインタープリタ上で処理する必要になる
・カウンタの操作もループごとにインタープリタ上で処理する必要になる
・append()はリストのメソッドであるため、
イテレーションごとに関数ルックアップの追加のコストが必要になる
>>> evens = [] >>> for i in range(10): ... if i % 2 == 0: ... evens.append(i) ... >>> evens [0, 2, 4, 6, 8]
下記のコードだと、処理の一部がインタープリタ内部で実行され、処理が早くなる。
>>> [i for i in range(10) if i % 2 == 0] [0, 2, 4, 6, 8]
辞書の弱点と対応策
辞書はキーの順序を保持しない(python3.6前後で挙動が違うらしい)。
必ず、下記の実行結果になるとは限らないので、
順序を保持するなら、OrderedDictを利用する。
>>> {number: None for number in range(5)}.keys() dict_keys([0, 1, 2, 3, 4]) >>> >>> {str(number): None for number in range(5)}.keys() dict_keys(['0', '1', '2', '3', '4']) >>> >>> from collections import OrderedDict >>> OrderedDict((str(number), None) for number in range(5)).keys() odict_keys(['0', '1', '2', '3', '4'])
Pythonの高度な文法
イテレータ, ジェネレータ, デコレータ, コンテキストマネージャについて
イテレータについて
イテレータはイテレータプロトコルを実装したコンテナオブジェクト
イテレータプロトコルは、下記2つのメソッドを持つ
・コンテナの次の要素を返す__next__()メソッド
・イテレータ自身を返す__iter__()メソッド
>>> i = iter('abcde') >>> next(i) 'a' >>> next(i) 'b' >>> next(i) 'c' >>> next(i) 'd' >>> next(i) 'e' >>> next(i) Traceback (most recent call last): File "<stdin>", line 1, in <module> StopIteration
# https://github.com/PacktPublishing/Expert-Python-Programming_Second-Edition/blob/master/chapter2/iterators.py ... class CountDown(): ... def __init__(self, step): ... self.step = step ... def __next__(self): ... # コンテナの次の要素を返す ... if self.step <= 0: ... raise StopIteration ... self.step -= 1 ... return self.step ... def __iter__(self): ... # イテレータ自身を返す ... return self ... >>> itr = CountDown(3) >>> next(itr) 2 >>> next(itr) 1 >>> next(itr) 0 >>> next(itr) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 8, in __next__ StopIteration >>> for element in CountDown(4): ... print(element) ... 3 2 1 0
ジェネレータについて
ジェネレータは反復可能なオブジェクト
イテレータ同様forなどでループ処理を行うことができ、
その都度必要な分だけ値を生成させることができるため、
メモリを効率的に使用することができる。
# https://github.com/PacktPublishing/Expert-Python-Programming_Second-Edition/blob/master/chapter2/yield_fibonacci.py >>> def fibonach(): ... a, b = 0, 1 ... while True: ... yield b ... a, b = b, a + b ... >>> fib = fibonach() >>> next(fib) 1 >>> next(fib) 1 >>> next(fib) 2 >>> next(fib) 3 >>> next(fib) 5 >>> next(fib) 8 >>> [next(fib) for i in range(10)] [13, 21, 34, 55, 89, 144, 233, 377, 610, 987]
# https://github.com/PacktPublishing/Expert-Python-Programming_Second-Edition/blob/master/chapter2/yield_psychologist.py >>> def psychologist(): ... print('あなたの悩みを聞かせてください') ... while True: ... answer = (yield) ... if answer is not None: ... if answer.endswith('?'): ... print("自分自身に問いかけをしすぎないようにしましょう") ... elif '良い' in answer: ... print("それは良いですね。ぜひやりましょう") ... elif '悪い' in answer: ... print("悲観的にならないようにしましょう") ... >>> free = psychologist() >>> next(free) あなたの悩みを聞かせてください >>> free.send('気分が悪いです') 悲観的にならないようにしましょう >>> free.send('なぜ私はすべきではないんでしょうか?') 自分自身に問いかけをしすぎないようにしましょう >>> free.send('なるほど。それなら何が私にとって良いかを探すべきですね') それは良いですね。ぜひやりましょう
コメント