根据我对 Python 面向对象编程的理解,如果一个类__call__定义了方法,如果我们像函数调用一样使用类的实例,就会调用该方法。例如:
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))
Run Code Online (Sandbox Code Playgroud)
因此该__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)
Run Code Online (Sandbox Code Playgroud)
现在根据书中给出的文档,元类__new__方法将由__call__从类型继承的方法运行。
现在我的问题是使用__call__ 任何类的方法,我们必须拥有该类的对象,然后将其作为函数调用。
这里我们没有任何类型的对象来使用它的__call__功能。
有人可以向我解释一下__call__type class的功能是如何出现的吗?
任何类本身都是“type”类型的实例——因此“调用”一个类只是调用__call__它的类上的方法——这恰好是类型的__call__. 的效果type.__call__正是:在代码上,如:
class A:
pass
b = A()
Run Code Online (Sandbox Code Playgroud)
type.__call__接收类A本身作为它的第一个参数。A.__new__- 在我们可以编写的伪代码中instace = A.__new__(cls)运行。 __init__实例( instance.__init__())return instance但是,如果类本身是从“类型”派生的——即,它是“新”类的实例化,则需要采取额外的步骤:__class__在任何类方法中填充魔法变量的特殊值——如果有的话这些方法中的一个使用调用super. 在 Python 3.6 上,还有以下 2 个步骤:__set_name__调用定义方法的任何类属性 ,然后调用类的__init_subclass__方法。
请记住,type是一个元类,因此它的实例是类,而不是对象。比意味着(除其他外)当你这样做时:
e= Employee(*args,**kwargs)
Run Code Online (Sandbox Code Playgroud)
您正在Employee.__init__调用元类中的一些方法,包括Meta.__call__,与您调用时的方式相同。
print (e(10))
Run Code Online (Sandbox Code Playgroud)
您正在调用您的自定义__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
Run Code Online (Sandbox Code Playgroud)
现在,每次创建 的新实例时MyClass,都会在创建实际实例之前__call__调用元类中的方法,从而允许您检查前一个实例是否存在并返回该实例。
希望这可以帮助。