今天我在Python中遇到了一个关于元类的令人惊讶的定义,这里有详细说明,并且元类的定义被内联了。 相关部分如下:
class Plugin(object):
class __metaclass__(type):
def __init__(cls, name, bases, dict):
type.__init__(name, bases, dict)
registry.append((name, cls))
何时使用这样的内联定义才有意义呢?
更进一步的论点:
支持该技术的一个论点是,使用这种技术创建的元类无法在其他地方重用。反驳的论点是,在使用元类的常见模式中,定义一个元类并在一个类中使用它,然后从那个类继承。例如,在保守元类中,有这样一个定义:
class DeclarativeMeta(type):
def __new__(meta, class_name, bases, new_attrs):
cls = type.__new__(meta, class_name, bases, new_attrs)
cls.__classinit__.im_func(cls, new_attrs)
return cls
class Declarative(object):
__metaclass__ = DeclarativeMeta
def __classinit__(cls, new_attrs): pass
可以写成以下方式:
class Declarative(object): #code not tested!
class __metaclass__(type):
def __new__(meta, class_name, bases, new_attrs):
cls = type.__new__(meta, class_name, bases, new_attrs)
cls.__classinit__.im_func(cls, new_attrs)
return cls
def __classinit__(cls, new_attrs): pass
还有其他需要考虑的问题吗?
module.classname
作为惰性加载的基础而没有使用eval
,但我可以看到相当多的doctest和测试套件受到影响。我想我会放弃这个方案。 - Muhammad Alkarourieval
进行惰性加载(那将非常愚蠢)-- 它们将使用__import__
和getattr
!-) - Alex Martellirepr
的更改影响(至少在url调度程序中使用时)。因此,我认为它们并不会在repr
问题上倾向于任何一方。 - Muhammad Alkarourirepr()
使用完全限定名称__qualname__
而不是__name__
。答案仍然有效,因为如上所述,__metaclass__
属性不再是Python 3+中使用元类的方式。 - Muhammad Alkarouri