类语法和type()有什么区别?

我很清楚这样一个事实,可以使用type在python中动态声明类,并且在各处使用了它。但是我仍然不清楚这两个功能之间有什么区别。

def class_factory():
    def init(self,attr):
        self.attr = attr
    class_ = type('DynamicClass',(),{'__init__' : init})
    return class_

def class_factory():
    class DynamicClass:
        def __init__(self,attr):
            self.attr = attr
    return DynamicClass

我已经看到许多代码库(如django)中使用的第一个模式,但是到目前为止,还没有见过第二个模式。从语法上来说,我仍然觉得第二个更清楚。

我正在努力寻找有关为什么人们使用first pattern声明动态类而不使用second的正确解释。我对这两个函数进行了实验,但发现从这两个函数获得的类之间没有显着差异。我希望能从任何方面(性能方面或其他方面)对上述两种模式/语法之间的差异进行清楚的解释。

谢谢

zyjzb258 回答:类语法和type()有什么区别?

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

大家都在问