Python __call __()这是一个隐式的类方法吗?

Jee*_*eva 2 python metaclass class-method python-3.x

我想在python中实现一个单例模式,我喜欢http://www.python-course.eu/python3_metaclasses.php中描述的模式.

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 SingletonClass(metaclass=Singleton):
    pass
class RegularClass():
    pass
x = SingletonClass()
y = SingletonClass()
print(x == y)
x = RegularClass()
y = RegularClass()
print(x == y) 
Run Code Online (Sandbox Code Playgroud)

代码工作得很完美.但是,__call__()没有self,它也没有@classmethod@staticmethod声明.

但是,在Python数据模型https://docs.python.org/3/reference/datamodel.html#object.__call__中,__call__()方法在参数中有一个self.

如果我通过self或声明为@staticmethod或,则代码不起作用@classmethod.

有人可以解释一下该__call__()方法背后的语法逻辑.

Mar*_*ers 9

命名方法的第一个参数cls或者self只是一个约定.该__call__方法确实有一个自我参数,只有它在这里命名 cls.那是因为对于元类,该方法绑定到一个类对象,名称反映了这一点.

同样的惯例适用于@classmethod方法; 由于classmethod对象如何绑定的性质,第一个参数总是一个类,所以命名第一个参数是有意义的cls.

但你可以自由地将第一个参数命名为其他任何东西.它不是使类方法或常规方法或方法在元类型上工作的名称.所有使用selfcls做的都是记录这是什么类型的对象,使其他开发人员更容易在心理上跟踪正在发生的事情.

所以不,这不是一个隐式的类方法.第一个参数没有绑定到Singleton元类对象,它被绑定到被调用的类.这是有道理的,因为该类对象是元类型的实例Singleton.

如果你想深入了解绑定是如何工作的(导致第一个参数传入的过程,无论名称如何),你可以阅读描述符HOWTO.TLDR:函数property,classmethodstaticmethod对象都是描述符,每当你访问它们作为属性支撑物上的,如实例或类,他们必然,往往导致不同的对象返回的结果,调用时将绑定对象传递给实际函数.