class
语句是对元类的调用的声明性语法。
class Foo(Bar,metaclass=SomeMeta): # If not specified,the metaclass is type
...
等同于
Foo = SomeMeta('Foo',(Bar,) {...})
其中{...}
是根据class
语句的主体构造的一些映射。只是一个简单的示例,而没有详细介绍:
class Foo(Bar,metaclass=SomeMeta):
some_attr = "foo string"
def __init__(self,x=9):
self.y = x = 3
将定义一个函数名称__init__
,然后将{'__init__': __init__,'some_attr': 'foo string'}
传递给SomeMeta
。名称__init__
仅存在于class
语句创建的临时命名空间中,而不会影响该语句外部可能存在的任何名称__init__
。
要回答您的问题,有时自己构造元类的第三个参数比让class
语句为您完成此操作更灵活或更简单。第二个参数也是如此。 first 参数由class
语句的语法固定,但是如果您自己调用元类,则可以在运行时生成。
请注意,这意味着您可以真的滥用class
语句。我认为,EnumMeta
模块中的enum
可以扩展您应做的事情。这是一个确实辱骂性的例子。实际上,元类不一定是类型。它只必须是可调用的,并且需要接受三个位置参数。它也可以接受其他关键字参数。然后,它可以使用这些参数执行所需的任何操作,并返回所需的任何操作。
def FooMeta(name,bases,dct,msg):
print(f'{msg} from {name}')
return 3
class Foo(metaclass=FooMeta,msg="hi"):
pass
Foo
甚至不是一堂课;它绑定到3
。
,
您选择了一个正确的示例,如何动态地创建第二个示例的类?您不能正确地做到这一点,这就是为什么首选第一种情况。看看这个基于您的玩具示例。
def class_factory(many_args=False):
def init1(self,attr):
self.attr = attr
def init2(self,*attr):
self.attr = attr
init = init1
if many_args:
init = init2
class_ = type('DynamicClass',(),{'__init__': init})
return class_
many = class_factory(True)(1,2,3,4)
one = class_factory()(1)
结果:
>>> print(many.attr,one.attr)
(1,4) 1
在第二个例子中,很难用不同的属性和方法组成一个类。
本文链接:https://www.f2er.com/3142948.html