__call__类型类的方法

时间:2017-05-25 10:26:22

标签: python metaclass

如果一个类定义了__call__方法,如果我们像函数调用一样使用类的实例,那么我就会理解Python面向对象编程。例如:

class Employee:
    def __init__(self,name,sal):
        self.name = name
        self.salary = sal
    def __call__(self,value):
        return self.salary * value

e = Employee("Subhayan",20000)
print (e(10))

因此__call__方法将对象实例作为第一个参数。

我只是想了解Python中的元类,我读到type是所有用户定义类的默认元类。

如果我在Python中定义基本的自定义元类:

class Meta(type):
    def __new__(meta, classname, supers, classdict):
        # Run by inherited type.__call__
        return type.__new__(meta, classname, supers, classdict)

现在根据本书中给出的文档,元类__new__方法将由从类型继承的__call__方法运行。

现在我的问题是使用我们拥有的任何类的__call__方法来获得该类的对象,然后将其称为函数。

这里我们没有任何类型的对象来使用它的__call__函数。

有人可以向我解释一下类型类的__call__功能是如何形成的?

2 个答案:

答案 0 :(得分:2)

任何类本身都是类型"类型"的实例。 - 因此"呼叫"一个类只调用其类中的方法__call__ - 恰好是类型__call__type.__call__的效果恰好如下: 代码如下:

class A:
    pass
b = A()
  1. type.__call__收到类A本身作为其第一个参数。
  2. 它调用A.__new__ - 在伪代码中我们可以编写instace = A.__new__(cls)作为运行。
  3. 返回" A"的实例类
  4. 然后它在实例(__init__
  5. 上调用instance.__init__()
  6. ...并返回该实例return instance
  7. 但是,如果类本身来自"类型" - 即,它是" new"的实例化。 class,采取额外步骤:在任何类方法中填充magic __class__变量的特殊值 - 如果这些方法中的任何一个使用对super的调用。在Python 3.6上,还有以下两个步骤:调用定义__set_name__方法的任何类属性,并调用类的__init_subclass__方法。

答案 1 :(得分:1)

请记住,type是一个元类,因此它的实例是类,而不是对象。当你这样做时,意味着(除其他外):

e= Employee(*args,**kwargs)

您正在调用Employee.__init__以及您的元类中的一些方法,包括Meta.__call__,与您的方法相同。

print (e(10))

您正在调用自定义__call__方法。

以此Singleton元类:

为例
class Singleton(type):
    _instances = {}
    def __call__(cls, *args, **kwargs):
        if cls not in cls._instances:
            cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
        return cls._instances[cls]

class MyClass(BaseClass):
    __metaclass__ = Singleton

现在,每次创建MyClass的新实例时,元类中的__call__方法都会被称为,之后创建实际实例,以便您检查以前是否存在一个存在并返回。

希望这有帮助。