文字列をreverseしてみます。
# coding: sjis for s in [u"こんにちは世界", u"Hello世界", u"こんにちはworld"]: print "".join(reversed(s))
実行結果です。
> python a.py 界世はちにんこ 界世olleH dlrowはちにんこ
>>> g = (x for x in range(5)) # ジェネレータ作成 >>> list(g) # リストを作る [0, 1, 2, 3, 4] >>> sum(g) # sumを得る 0 # 10じゃないの? >>> g.next() Traceback (most recent call last): File "<stdin>", line 1, in ? StopIteration # おっと、いけない。既にお尻にきてたのだった >>> sum(x for x in range(5)) 10
結城さんの『結城 浩のPerlクイズ』のp.25に「自己言及的スクリプト」というのがあります。実行するとスクリプトの内容と同じ文字列が表示されるスクリプトです。それをPythonで書いてみました。
x = ';print "x = %s%s" % (foo(x), x)';print "x = %s%s" % (foo(x), x)
うまくかけなかったので、fooという関数を使ってしまいました。
def foo(a): return "'%s'" % a
追記:reprが使えました。
x = ';print "x = %s%s" % (repr(x), x)';print "x = %s%s" % (repr(x), x)
さらに追記:バッククオートも使えました。
x = ';print "x = %s%s" % (`x`, x)';print "x = %s%s" % (`x`, x)
バッククオート内に書かれた式(のリスト)は、そのオブジェクトに対応する文字列に変換されます。
lambda でタプルを返そうと思い、次のように書きましたがエラーになります。
>>> a = (lambda x: x, x)(10) Traceback (most recent call last): File "<stdin>", line 1, in ? NameError: name 'x' is not defined
これは、
a = ((lambda x: x), x)(10)
という風に解釈されます。エラーメッセージが分かりにくいので、x のところを例えば 1 にしてみると、
>>> a = (lambda x: x, 1)(10) Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: 'tuple' object is not callable
タプルが生成されて、それに対して () で呼び出しをしようとしているのが分かります。
返したいタプルをちゃんと括弧で囲めば問題ありません。
>>> a = (lambda x: (x, x))(10) >>> a (10, 10)
>>> it = iter([1, 2, 3]) >>> it.next() 1 >>> it.next() 2 >>> it.next() 3 >>> it.next() Traceback (most recent call last): File "<stdin>", line 1, in ? StopIteration >>> it = iter({ 1: 2, 3: 4 }) >>> it.next() 1 >>> it.next() 3 >>> it.next() Traceback (most recent call last): File "<stdin>", line 1, in ? StopIteration
"インスタンス()" とすると、__call__ メソッドが呼び出されます。
>>> class Counter: ... def __init__(self, n=0): ... self.n = n ... def __call__(self): ... self.n += 1 ... return self.n ... >>> counter = Counter() >>> counter() 1 >>> counter() 2 >>> counter() 3 >>> counter2 = Counter(10) >>> counter2() 11 >>> counter2() 12
% 演算子の右側にディクショナリを指定して、変換指定子の % の後に '(hoge)' のように括弧でディクショナリのキー(文字列)を指定できます。
>>> d = { "foo": "Hello", "bar": "World" } >>> "%(foo)s %(bar)s" % d 'Hello World'
dis モジュールを使うと Python バイトコードを逆アセンブル出来ます。
>>> def foo(): ... lst.reverse() ... >>> import dis >>> dis.dis(foo) 2 0 LOAD_GLOBAL 0 (lst) 3 LOAD_ATTR 1 (reverse) 6 CALL_FUNCTION 0 9 POP_TOP 10 LOAD_CONST 0 (None) 13 RETURN_VALUE
これを見ると 'lst.reverse()' とは lst の reverse 属性を取り出し、それを呼び出しているのが分かります。なので次のような書き方も出来ます。
>>> lst = [] >>> append = lst.append >>> lst [] >>> append(12) >>> lst [12]
ジェネレータは名前のとおり値を生み出します。yieldに渡される値が、生み出される値になります。
>>> def foo(): # 10を生み出すジェネレータ ... yield 10 ... >>> g = foo() >>> g.next() 10 >>> g.next() Traceback (most recent call last): File "<stdin>", line 1, in ? StopIteration
generatorに対しnextメソッドで生み出された値を取得できます。nextメソッドを呼び出したときに、もう値がないならStopIteration例外が生成されます。
>>> def bar(n): # n,n+1,n+2を生み出すジェネレータ ... yield n ... yield n+1 ... yield n+2 ... >>> g = bar(10) >>> g.next() 10 >>> g.next() 11 >>> g.next() 12 >>> g.next() Traceback (most recent call last): File "<stdin>", line 1, in ? StopIteration >>> list(bar(5)) [5, 6, 7]
「1 < x and x < 4」は「1 < x < 4」と書けます。
>>> 1 < 2 < 3 True >>> 1 < 5 < 3 False >>> x = 10 >>> 1 < x < 10 False >>> 1 < x < 90 True
class Foo: pass class Bar: pass >>> isinstance(Foo(), Foo) True >>> isinstance(Bar(), Foo) False
また、オブジェクトの同一性を調べるには is を使います。type を使うと、それがインスタンスなのか、クラスオブジェクトなのか等を調べる事が出来ます。
>>> type(Foo()) <type 'instance'> >>> type(Foo) <type 'classobj'> >>> foo, bar = Foo(), Foo() >>> foo is bar False >>> type(foo) is type(bar) True
引数名によって値を対応付けてくれます。
def foo(a, b): print a, b
>>> foo(1, 2) 1 2 >>> foo(a=10, b=3) 10 3 >>> foo(b=2, a=8) 8 2 >>> foo(a=1, 4) SyntaxError: non-keyword arg after keyword arg >>> foo(2, b=1) 2 1 >>> foo(3, c=9) TypeError: foo() got an unexpected keyword argument 'c'
returnがなければ、関数からNone返されます。
>>> def bad(): ... 10 ... >>> r = bad() >>> type(r) <type 'NoneType'>
リファレンスマニュアルによると:
デフォルトパラメタ値は関数定義を実行する際に値評価されます。 これは、デフォルトパラメタの式は関数を定義するときにただ一度だけ評価され、同じ ``計算済みの'' 値が全ての呼び出しで使われることを意味します。
>>> def foo(a=[]): ... print len(a) ... a.append(1) ... >>> foo() 0 >>> foo() 1 >>> foo() 2
lambda は式のみ。
>>> lambda x: if x > 0: return 5 File "<stdin>", line 1 lambda x: if x > 0: return 5 ^ SyntaxError: invalid syntax