python中元类的__call__方法的作用

元类是类的类,元类之于类就相当于类之于实例。

元类的new方法会创建一个类并返回,就像类的new方法会创建一个实例并返回一样。

元类中其他方法的定义类似于类中方法的定义,例如:

class Meta(type):
  def __new__(cls, name, bases, dct): # cls为元类Meta
    return type.__new__(cls, name, bases, dct)

  def foo(cls, *args, **kwargs): # cls为元类创建的类
    pass

  def __call__(cls, *args, **kwargs): # cls为元类创建的类
    pass

元类中有一个特殊的方法__call__,这个方法会阶段类的__new____init__

__call__ 应该返回实例,和类的__new__方法返回的一样。

class Meta(type):
  def __new__(cls, name, bases, dct):
    print("calling Meta's __new__", cls)
    return type.__new__(cls, name, bases, dct)

  def __call__(cls, *args, **kwargs):    
    print("calling Meta's __call__", cls)
    i = cls.__new__(cls)
    i.__init__(*args, **kwargs)
    return i

class A(object):
  __metaclass__ = Meta

  def __new__(cls, *args, **kwargs):
    print("calling A's __new__")
    return object.__new__(cls)

  def __init__(self, *args, **kwargs):
    print("calling A's __init__")

a = A()
print("a is", a)

calling Meta's __new__ <class '__main__.Meta'>
calling Meta's __call__ <class '__main__.A'>
calling A's __new__
calling A's __init__
a is <__main__.A object at 0x7faadaf02390>

此时,还不太能看出来Meta.call拦截了A.__new__A.__init__,只能看出,__call__会先于__new____init__调用。(其实可以看出,如果没有拦截发生,calling A's __new__calling A's __init__会输出两次

 

posted @ 2018-12-28 17:22  small_lei_it  阅读(669)  评论(0)    收藏  举报