Python元类和特殊方法

时间:2014-04-02 21:44:59

标签: python metaclass

我尝试使用元类来使用自定义特殊方法生成类 - 特别是__call__。类的生成取决于调用构造函数的参数。我遇到了一个奇怪的效果,简化示例如下:

def trick(self, *args, **kwargs):
    print "Works!"

class Test1Factory(type):
    def __new__(mcls, name, bases, namespace):
        namespace['__call__'] = trick
        return type.__new__(mcls, name, bases, namespace)


class Test1(object):
    __metaclass__ = Test1Factory

    def __init__(self, value):
        self._value = value


t1 = Test1(1)
t1() # "Works!"

它有效,但它并不真正有用,因为__new__中无法访问构造函数参数。 type.__call__应该做到这一点:

import types
class Test2Factory(type):
    def __call__(self, *args, **kwargs):
        obj = type.__call__(self, *args, **kwargs)
        setattr(obj, '__call__', types.MethodType(trick, obj, Test2))

        return obj

class Test2(object):
    __metaclass__ = Test2Factory

    def __init__(self, value):
        self._value = value

t2 = Test2(2)
t2.__call__() # "Works!"
t2() # TypeError: 'Test2' object is not callable

据我了解,instance()instance.__call__()类似,但在此情况并非如此。使用类的__new__静态方法也是如此。我有一个根本不使用元类的解决方法,但只想了解这些现象。 Python版本是2.7.5

1 个答案:

答案 0 :(得分:0)

错误的假设可能在“instance()instance.__call__()类似”,因为在__call__中没有查找instance,而是在实例的类型中。也就是说,使用的__call__不是instance的{​​{1}},而是instance.__class__type(instance)的。{/ p>

__call__上定义的任何instance属性都可以作为任何其他属性定期访问,但在instance调用instance()时不会使用。这是Python语义的一部分。

尝试在实例及其类型上定义__call__,看看你得到了什么。

如果我正确地理解了这个问题,那么这个问题与我的另一个问题具有相同的背景,并且得到了答案(在问题的帖子中通过实验进行了演示):“How do Python tell “this is called as a function”?”。