【问题标题】:Python metaclasses and special methodsPython 元类和特殊方法
【发布时间】:2014-05-14 11:03:20
【问题描述】:

我尝试使用元类来使用自定义特殊方法生成类 - 特别是 __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

【问题讨论】:

  • 特殊方法在类而不是实例中查找。
  • @Aशwiniचhaudhary - 是的,这回答了问题。使用调度是我的解决方法,我想这是唯一的方法。

标签: python metaclass


【解决方案1】:

错误的假设可能出现在“instance() is similar to instance.__call__()”中,因为__call__不是在instance中查找,而是在实例的类型中查找。也就是说,使用的__call__不是instance,而是instance.__class__type(instance)

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

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

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

【讨论】:

    猜你喜欢
    • 2014-07-15
    • 1970-01-01
    • 2015-02-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-21
    • 2019-03-16
    相关资源
    最近更新 更多