7

免責事項これは単なるメタプログラミングの演習であり、実用的な目的はありません。

__getitem__関数オブジェクトにandメソッドを割り当てまし__getattr__たが、効果がありません...

def foo():
  print "foo!"

foo.__getitem__ = lambda name: name
foo.__getattr__ = lambda name: name
foo.baz = 'baz'

プロパティを関数に割り当てることができることを確認します。

>>> foo.baz
'baz'

きちんとした。「魔法のゲッターズ」はどうですか?

>>> foo.bar
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'function' object has no attribute 'bar'

>>> foo['foo']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'function' object is not subscriptable

>>> getattr(foo, 'bar')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'function' object has no attribute 'bar'

関数オブジェクトに「魔法のゲッター」を持たせることは可能ですか?

4

3 に答える 3

6

いいえ!__getitem__インスタンスへの割り当ては、どのタイプのオブジェクトでも機能しません。

>>> class A(object):
...   pass
...
>>> a = A()
>>> a.__getattr__ = lambda name: name
>>> a.foo
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'A' object has no attribute 'foo'

また__getattr__、組み込み関数型で定義することはできません:

>>> import types
>>> types.FunctionType.__getitem__ = lambda name: name
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can't set attributes of built-in/extension type 'function'

そして、サブクラス化することはできませんtypes.FunctionType:

>>> import types
>>> class F(types.FunctionType):
...   pass
... 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Error when calling the metaclass bases
type 'function' is not an acceptable base type
于 2012-05-29T16:48:23.677 に答える
3

少なくとも新しいスタイルのクラス (Python 3 で唯一の種類であり、Python 2 で使用する必要がある種類) では、Python はクラス (およびその祖先) のマジック メソッドのみを検索し、インスタンスでは検索しません。ドキュメントはこちら

もちろん、関数の型を変更したり、そこから派生したりすることはできません。ただし、おわかりのように、メソッドを持つクラスはすべて__call__()呼び出し可能なインスタンスを作成するため、それを行う方法です。

于 2012-05-29T17:14:49.803 に答える
2

ああ!を使用__call__し、関数をラップしますF()

class F(object):
    def __init__(self, fn):
        self.__dict__['fn'] = fn

    def __call__(self, *args, **kwargs):
        return self.fn(*args, **kwargs)

    def __getitem__(self, name):
        return name

    def __getattr__(self, name):
        return name

>>> foo = F(foo)
>>> f.bar
'bar'
>>> f['foo']
'foo'
>>> foo()
foo!
于 2012-05-29T16:58:30.747 に答える