ご褒美にクソの役にも立たない Python 豆知識が手に入る話

オイシイ話ばっかり、ってわけでもなくて。

古いものも大事よね、ってことで What’s old てるわけなんだけれど、そんなかで「なにそれ食べれるの」を発見。

1 def f(): pass
2 
3 f.publish = 1
4 f.secure = 1
5 f.grammar = "A ::= B (C D)*"

Python 2.1 から出来るようになった「関数の属性」、の話。Python 2.7 ですら「時代遅れも甚だしい」くらいのイキオイになりつつある今となっては、ほとんど空気のように当たり前に享受してるようなこと、これ自体は。(まぁ関数に属性を付けてやるぜ! ってあえて思うわけではなくて、プロキシパターンやらなんやら使ってると自然に使っておるのでね。)

問題なのはこの本題ではなくてこの一文:

The dictionary containing attributes can be accessed as the function’s :attr:`__dict__`. Unlike the :attr:`__dict__` attribute of class instances, in functions you can actually assign a new dictionary to :attr:`__dict__`, though the new value is restricted to a regular Python dictionary; you *can’t* be tricky and set it to a :class:`UserDict` instance, or any other random object that behaves like a mapping.

ワタシが訳出したのはこんなね:

属性を含んだ辞書に、関数の属性 :attr:`__dict__` としてアクセス出来ます。クラスインスタンスの :attr:`__dict__` 属性とは違って、関数では実際には、 :attr:`__dict__` に別の辞書を代入出来ます。ですが、新しい値は普通の Python 辞書に制限されています; ズルは *出来ません* し、 :class:`UserDict` インスタンスやなにかほかのマッピングのように振舞うデタラメなオブジェクトはセット出来ません。

なぬ? __dict__ を上書き出来ちゃうの?? __dict__ なんぞは許されてても読み取り専用で使うもんだろ、と思うのでどっちでもまぁいいんだけど、なんでこれ、「出来ちゃう」んであろうか?

今でも出来んの?

2.7.9
 1 Python 2.7.9 (default, Dec 10 2014, 12:28:03) [MSC v.1500 64 bit (AMD64)] on win32
 2 Type "help", "copyright", "credits" or "license" for more information.
 3 >>> def f(): pass
 4 ...
 5 >>> f.a = 1
 6 >>> f.__dict__
 7 {'a': 1}
 8 >>> f.__dict__ = {}
 9 >>> f.__dict__
10 {}
11 >>> 
3.4.3
 1 Python 3.4.3 (v3.4.3:9b73f1c3e601, Feb 24 2015, 22:43:06) [MSC v.1600 32 bit (Intel)] on win32
 2 Type "help", "copyright", "credits" or "license" for more information.
 3 >>> def f(): pass
 4 ...
 5 >>> f.a = 1
 6 >>> f.__dict__
 7 {'a': 1}
 8 >>> f.__dict__ = {}
 9 >>> f.__dict__
10 {}
11 >>> 

出来ますわね。

どういう用途があるんだろうか、差し替えれると…。なんかセキュリティ的なこととかに、…とか?