元类可以有方法吗?
Can metaclasses have methods?
我正在尝试为我的项目实现单例 classes,并在 Whosebug 中实现一个有趣的 post 同样
Creating a singleton in Python
我决定采用提到的元classes 方法..
现在..我尝试添加一个方法来获取和清除实例(以防用户想要摆脱当前实例并创建一个新实例..):
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]
def getInstance(cls):
print("Class is {}".format(cls.__name__))
if not cls in cls._instances:
raise LookupError("No instance of the class {cls} create yet.".format(cls.__name__))
return cls._instances[cls]
def clearInstance(cls):
cls._instances.pop(cls, None)
class someClass(metaclass=Singleton):
def __init__(self,val):
self.value = val
我能够成功创建对象..
In [9]: sc = someClass(1)
In [10]: sc.value
Out[10]: 1
但是当我执行 dir(someClass)
时,没有显示 2 个方法:
In [14]: dir(someClass)
Out[14]:
['__class__',
'__delattr__',
'__dict__',
'__dir__',
'__doc__',
'__eq__',
'__format__',
'__ge__',
'__getattribute__',
'__gt__',
'__hash__',
'__init__',
'__le__',
'__lt__',
'__module__',
'__ne__',
'__new__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__setattr__',
'__sizeof__',
'__str__',
'__subclasshook__',
'__weakref__']
不过我可以调用方法..
In [13]: someClass.getInstance()
Class is someClass
Out[13]: <__main__.someClass at 0x7f728b180860>
在 metaclass 上的所有示例中,我在网上看到我看到 __new__
、__init__
和 __call__
方法已实现,但我没有看到添加任何其他方法.向元class添加方法是否正确?
我还尝试了上述元class代码的一个小变体:
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]
@classmethod
def getInstance(cls):
print("Class is {}".format(cls.__name__))
if not cls in cls._instances:
raise LookupError("No instance of the class {cls} create yet.".format(cls.__name__))
return cls._instances[cls]
@classmethod
def clearInstance(cls):
cls._instances.pop(cls, None)
将这 2 个方法标记为 class 方法..
现在,当我尝试给他们打电话时:
In [2]: sc = someClass(1)
In [3]: someClass.getInstance()
Class is Singleton
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
<ipython-input-3-c83fe01aa254> in <module>()
----> 1 someClass.getInstance()
<ipython-input-1-9efb6548d92d> in getInstance(cls)
12
13 if not cls in cls._instances:
---> 14 raise LookupError("No instance of the class {cls} create yet.".format(cls.__name__))
15
16 return cls._instances[cls]
KeyError: 'cls'
如您所见,当我将其装饰为 classmethod
时,class is
印刷品显示为 Singleton
。否则它会显示正确的 class。我不明白这种行为,有人可以解释一下吗?
类 是它们的元classes 的实例。正如 classes 的实例没有 class 的方法作为属性但仍然可以调用它们一样,classes 没有 meta[=12= 的方法] 作为属性。
Can python metaclasses have methods?
是的,正如您的第一个示例所示,它们可以具有方法,并且可以在实现您的元class的classes 上调用它们class。
例如在 python-3.x 中,metaclass type
实现了 mro
属性:
>>> object.mro()
[object]
但您无法在实例上访问它们:
>>> object().mro()
AttributeError: 'object' object has no attribute 'mro'
But when I do dir(someClass)
the 2 methods are not displayed.
dir
调用 type.__dir__
并且只显示了有限数量的方法:
If the object is a type or class object, the list contains the names of its attributes, and recursively of the attributes of its bases.
此处未提及 metaclass 的方法。那是因为它们默认是隐藏的。
这就是为什么您也看不到 mro
方法的原因:
>>> 'mro' in dir(object)
False
但是 dir
允许自定义您看到的内容,因此您可以简单地覆盖它。因为 __dir__
是在“实例的 class” 上调用的,而你的“metaclass 是你的 class 的类型”,你必须在你的 metaclass:
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]
def getInstance(cls):
print("Class is {}".format(cls.__name__))
if not cls in cls._instances:
raise LookupError("No instance of the class {cls} create yet.".format(cls.__name__))
return cls._instances[cls]
def clearInstance(cls):
cls._instances.pop(cls, None)
def __dir__(self):
normal_dir = type.__dir__(self)
# Also include all methods that don't start with an underscore and
# not "mro".
normal_dir.extend([
f for f in dir(type(self))
if not f.startswith('_')
and f != 'mro'
])
return normal_dir
class someClass(metaclass=Singleton):
def __init__(self,val):
self.value = val
>>> dir(someClass)
[..., 'clearInstance', 'getInstance']
现在,您 class 的这些方法在您调用 dir
时可见。
Is it correct to add methods to the metaclass?
这在一定程度上取决于上下文。我会说将这些方法添加到 metaclass 中很好。但是,这些应该很少使用。
As you can see the class is print says its Singleton when I decorate it as classmethod
. Otherwise it shows the correct class. I don't understand this behavior, can someone explain?
你想想就明白了。 Singleton
是您的 someClass
的 class,当您将其设为 classmethod
时,cls
参数将为 Singleton
。但是 class 添加到 _instances
是 someClass
。我可以看到它来自哪里。您所有的方法都采用 cls
参数。这可能让你相信它们是“像”class方法(它们在某种程度上是,但不是元class而是实现元class的class ]!).
但这只是一个约定,因为 self
是 class
实例的典型参数名称,cls
是 a 实例的典型参数名称metaclass
。当你的 metaclass 上有 class 方法时,第一个参数可能应该被称为 metacls
。还解决了 str.format
的一个小问题(这就是它抛出 KeyError
而不是 LookupError
的原因):
class Singleton(type):
_instances = {}
def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
print(cls._instances) # print the dict after creating an instance
return cls._instances[cls]
@classmethod
def getInstance(metacls):
print("Class is {}".format(metacls))
if not metacls in metacls._instances:
raise LookupError("No instance of the class {0} create yet.".format(metacls.__name__))
return metacls._instances[metacls]
@classmethod
def clearInstance(metacls):
metacls._instances.pop(metacls, None)
class someClass(metaclass=Singleton):
def __init__(self,val):
self.value = val
>>> sc = someClass(1)
{<class '__main__.someClass'>: <__main__.someClass object at 0x00000235844F8CF8>}
>>> someClass.getInstance()
Class is <class '__main__.Singleton'>
LookupError: No instance of the class Singleton create yet.
因此,您将“class”添加到字典中,然后检查元class 是否在字典中(它不在)。
通常自定义 classmethods
(除了那些 should/could 是 class 方法,例如 __prepare__
)在 metaclass 上没有多大意义,因为您很少需要实例的 class 类型。
Can python metaclasses have methods?
是的。
But when I do dir(someClass) the 2 methods are not displayed
与您可能相信的相反,dir
doesn't show everything:
Because dir()
is supplied primarily as a convenience for use at an interactive prompt, it tries to supply an interesting set of names more than it tries to supply a rigorously or consistently defined set of names, and its detailed behavior may change across releases. For example, metaclass attributes are not in the result list when the argument is a class.
As you can see the class is print says its Singleton when I decorate it as classmethod.
不要用classmethod
装饰它! 明确表示 您希望该方法在 Singleton
本身或 Singleton
的子 类 上运行,而不是 Singleton
的实例。 类 以 Singleton
作为它们的元类是单例的 实例 ;他们是 类 的事实并不是将 classmethod
放在 Singleton
的方法上的理由。
我正在尝试为我的项目实现单例 classes,并在 Whosebug 中实现一个有趣的 post 同样
Creating a singleton in Python
我决定采用提到的元classes 方法..
现在..我尝试添加一个方法来获取和清除实例(以防用户想要摆脱当前实例并创建一个新实例..):
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]
def getInstance(cls):
print("Class is {}".format(cls.__name__))
if not cls in cls._instances:
raise LookupError("No instance of the class {cls} create yet.".format(cls.__name__))
return cls._instances[cls]
def clearInstance(cls):
cls._instances.pop(cls, None)
class someClass(metaclass=Singleton):
def __init__(self,val):
self.value = val
我能够成功创建对象..
In [9]: sc = someClass(1)
In [10]: sc.value
Out[10]: 1
但是当我执行 dir(someClass)
时,没有显示 2 个方法:
In [14]: dir(someClass)
Out[14]:
['__class__',
'__delattr__',
'__dict__',
'__dir__',
'__doc__',
'__eq__',
'__format__',
'__ge__',
'__getattribute__',
'__gt__',
'__hash__',
'__init__',
'__le__',
'__lt__',
'__module__',
'__ne__',
'__new__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__setattr__',
'__sizeof__',
'__str__',
'__subclasshook__',
'__weakref__']
不过我可以调用方法..
In [13]: someClass.getInstance()
Class is someClass
Out[13]: <__main__.someClass at 0x7f728b180860>
在 metaclass 上的所有示例中,我在网上看到我看到 __new__
、__init__
和 __call__
方法已实现,但我没有看到添加任何其他方法.向元class添加方法是否正确?
我还尝试了上述元class代码的一个小变体:
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]
@classmethod
def getInstance(cls):
print("Class is {}".format(cls.__name__))
if not cls in cls._instances:
raise LookupError("No instance of the class {cls} create yet.".format(cls.__name__))
return cls._instances[cls]
@classmethod
def clearInstance(cls):
cls._instances.pop(cls, None)
将这 2 个方法标记为 class 方法..
现在,当我尝试给他们打电话时:
In [2]: sc = someClass(1)
In [3]: someClass.getInstance()
Class is Singleton
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
<ipython-input-3-c83fe01aa254> in <module>()
----> 1 someClass.getInstance()
<ipython-input-1-9efb6548d92d> in getInstance(cls)
12
13 if not cls in cls._instances:
---> 14 raise LookupError("No instance of the class {cls} create yet.".format(cls.__name__))
15
16 return cls._instances[cls]
KeyError: 'cls'
如您所见,当我将其装饰为 classmethod
时,class is
印刷品显示为 Singleton
。否则它会显示正确的 class。我不明白这种行为,有人可以解释一下吗?
类 是它们的元classes 的实例。正如 classes 的实例没有 class 的方法作为属性但仍然可以调用它们一样,classes 没有 meta[=12= 的方法] 作为属性。
Can python metaclasses have methods?
是的,正如您的第一个示例所示,它们可以具有方法,并且可以在实现您的元class的classes 上调用它们class。
例如在 python-3.x 中,metaclass type
实现了 mro
属性:
>>> object.mro()
[object]
但您无法在实例上访问它们:
>>> object().mro()
AttributeError: 'object' object has no attribute 'mro'
But when I do
dir(someClass)
the 2 methods are not displayed.
dir
调用 type.__dir__
并且只显示了有限数量的方法:
If the object is a type or class object, the list contains the names of its attributes, and recursively of the attributes of its bases.
此处未提及 metaclass 的方法。那是因为它们默认是隐藏的。
这就是为什么您也看不到 mro
方法的原因:
>>> 'mro' in dir(object)
False
但是 dir
允许自定义您看到的内容,因此您可以简单地覆盖它。因为 __dir__
是在“实例的 class” 上调用的,而你的“metaclass 是你的 class 的类型”,你必须在你的 metaclass:
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]
def getInstance(cls):
print("Class is {}".format(cls.__name__))
if not cls in cls._instances:
raise LookupError("No instance of the class {cls} create yet.".format(cls.__name__))
return cls._instances[cls]
def clearInstance(cls):
cls._instances.pop(cls, None)
def __dir__(self):
normal_dir = type.__dir__(self)
# Also include all methods that don't start with an underscore and
# not "mro".
normal_dir.extend([
f for f in dir(type(self))
if not f.startswith('_')
and f != 'mro'
])
return normal_dir
class someClass(metaclass=Singleton):
def __init__(self,val):
self.value = val
>>> dir(someClass)
[..., 'clearInstance', 'getInstance']
现在,您 class 的这些方法在您调用 dir
时可见。
Is it correct to add methods to the metaclass?
这在一定程度上取决于上下文。我会说将这些方法添加到 metaclass 中很好。但是,这些应该很少使用。
As you can see the class is print says its Singleton when I decorate it as
classmethod
. Otherwise it shows the correct class. I don't understand this behavior, can someone explain?
你想想就明白了。 Singleton
是您的 someClass
的 class,当您将其设为 classmethod
时,cls
参数将为 Singleton
。但是 class 添加到 _instances
是 someClass
。我可以看到它来自哪里。您所有的方法都采用 cls
参数。这可能让你相信它们是“像”class方法(它们在某种程度上是,但不是元class而是实现元class的class ]!).
但这只是一个约定,因为 self
是 class
实例的典型参数名称,cls
是 a 实例的典型参数名称metaclass
。当你的 metaclass 上有 class 方法时,第一个参数可能应该被称为 metacls
。还解决了 str.format
的一个小问题(这就是它抛出 KeyError
而不是 LookupError
的原因):
class Singleton(type):
_instances = {}
def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
print(cls._instances) # print the dict after creating an instance
return cls._instances[cls]
@classmethod
def getInstance(metacls):
print("Class is {}".format(metacls))
if not metacls in metacls._instances:
raise LookupError("No instance of the class {0} create yet.".format(metacls.__name__))
return metacls._instances[metacls]
@classmethod
def clearInstance(metacls):
metacls._instances.pop(metacls, None)
class someClass(metaclass=Singleton):
def __init__(self,val):
self.value = val
>>> sc = someClass(1)
{<class '__main__.someClass'>: <__main__.someClass object at 0x00000235844F8CF8>}
>>> someClass.getInstance()
Class is <class '__main__.Singleton'>
LookupError: No instance of the class Singleton create yet.
因此,您将“class”添加到字典中,然后检查元class 是否在字典中(它不在)。
通常自定义 classmethods
(除了那些 should/could 是 class 方法,例如 __prepare__
)在 metaclass 上没有多大意义,因为您很少需要实例的 class 类型。
Can python metaclasses have methods?
是的。
But when I do dir(someClass) the 2 methods are not displayed
与您可能相信的相反,dir
doesn't show everything:
Because
dir()
is supplied primarily as a convenience for use at an interactive prompt, it tries to supply an interesting set of names more than it tries to supply a rigorously or consistently defined set of names, and its detailed behavior may change across releases. For example, metaclass attributes are not in the result list when the argument is a class.
As you can see the class is print says its Singleton when I decorate it as classmethod.
不要用classmethod
装饰它! 明确表示 您希望该方法在 Singleton
本身或 Singleton
的子 类 上运行,而不是 Singleton
的实例。 类 以 Singleton
作为它们的元类是单例的 实例 ;他们是 类 的事实并不是将 classmethod
放在 Singleton
的方法上的理由。