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('なるほど。それなら何が私にとって良いかを探すべきですね')
それは良いですね。ぜひやりましょう

コメント