Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/354.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 类语法和type()之间有什么区别?_Python_Class_Dynamic_Dynamic Class Creation_Dynamic Class - Fatal编程技术网

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

Python 类语法和type()之间有什么区别?,python,class,dynamic,dynamic-class-creation,dynamic-class,Python,Class,Dynamic,Dynamic Class Creation,Dynamic Class,我很清楚,类可以使用类型在python中动态声明,并且在这里和那里都使用过它。但我仍然不清楚这两种功能之间的区别 def class_factory(): def init(self, attr): self.attr = attr class_ = type('DynamicClass', (), {'__init__' : init}) return class_ 及 我在django这样的代码库中看到了第一种模式,但到目前为止还没有看到第二种模式。

我很清楚,类可以使用类型在python中动态声明,并且在这里和那里都使用过它。但我仍然不清楚这两种功能之间的区别

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

我在django这样的代码库中看到了第一种模式,但到目前为止还没有看到第二种模式。但我发现第二个在句法上更清晰

我正在努力寻找关于为什么人们使用第一种模式来声明动态类而不是第二种模式的正确解释。我对这两个函数进行了实验,没有发现从这两个函数获得的类之间有任何显著的差异。我希望能从性能方面或其他方面对上述两种模式/语法之间的差异做出明确的解释


谢谢,

您选择了正确的示例,如何使用第二个示例动态创建一个类?你不能很好地做到这一点,这就是为什么第一种情况更可取的原因。看看这个基于你的玩具的例子

def class_factorymany_args=False: def init1self,属性: self.attr=attr def init2self,*属性: self.attr=attr init=init1 如果有多个参数: init=init2 类=类型'DynamicClass',{'''uuuuuu init':init} 返回舱_ 多=1、2、3、4级工厂 一个=一级工厂1 结果:

>>>printmany.attr,one.attr 1, 2, 3, 4 1
在第二个示例中,很难用不同的属性和方法组成一个类

如果您选择了正确的示例,如何使用第二个示例动态创建一个类?你不能很好地做到这一点,这就是为什么第一种情况更可取的原因。看看这个基于你的玩具的例子

def class_factorymany_args=False: def init1self,属性: self.attr=attr def init2self,*属性: self.attr=attr init=init1 如果有多个参数: init=init2 类=类型'DynamicClass',{'''uuuuuu init':init} 返回舱_ 多=1、2、3、4级工厂 一个=一级工厂1 结果:

>>>printmany.attr,one.attr 1, 2, 3, 4 1 在第二个示例中,很难用不同的属性和方法组成一个类

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
将定义一个函数名uuu init uuuuuuuuuu,然后将{‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘’。名称_uinit _uuuuuuuuu仅存在于class语句创建的临时名称空间中,而不影响可能存在于该语句之外的任何名称_uinit uuuuuuuu

为了回答您的问题,有时自己构造元类的第三个参数要比让class语句为您做更灵活或更简单。第二个论点也是如此。第一个参数由class语句的语法固定,但如果您自己调用元类,则可以在运行时生成

请注意,这意味着您确实可以滥用class语句。在我看来,enum模块中的EnumMeta扩展了您应该使用它的功能。这里有一个非常辱骂的例子。元类实际上不必是类型;它必须是可调用的,并且需要接受三个位置参数。它还可以接受其他关键字参数。然后,它可以用这些参数做任何它想做的事情,也可以返回任何它想返回的东西

def FooMeta(name, bases, dct, msg):
    print(f'{msg} from {name}')
    return 3

class Foo(metaclass=FooMeta, msg="hi"):
    pass
福甚至不是一个班级;它绑定到3。

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
将定义一个函数名uuu init uuuuuuuuuu,然后将{‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘’。名称_uinit _uuuuuuuuu仅存在于class语句创建的临时名称空间中,而不影响可能存在于该语句之外的任何名称_uinit uuuuuuuu

为了回答您的问题,有时自己构造元类的第三个参数要比让class语句为您做更灵活或更简单。第二个论点也是如此。第一个参数由class语句的语法固定,但如果您自己调用元类,则可以在运行时生成

请注意,这意味着您确实可以滥用class语句。在我看来,enum模块中的EnumMeta扩展了您应该使用它的功能。这里有一个非常辱骂的例子。元类实际上不必是类型;它必须是可调用的,并且需要接受三个位置参数。它还可以接受其他关键字参数。然后,它可以用这些参数做任何它想做的事情,也可以返回任何它想返回的东西

def FooMeta(name, bases, dct, msg):
    print(f'{msg} from {name}')
    return 3

class Foo(metaclass=FooMeta, msg="hi"):
    pass
福甚至不是一个班级;这是必然的
3.

您可以在class语句中放入if语句,根据多个参数的值选择要使用的uu init_uu的定义,仍然可以分配DynamicClass.\uuuu init\uuuuu=init2 if many_args else init1。您可以在class语句中放置一个if语句,根据多个_args的值选择要使用的\uuuu init\uuuuu的定义,我们仍然可以分配DynamicClass.\uuu init\uuuu=init2,如果许多参数都是init1,那么基本上第一个语法通过让我们构造元类的第一个和第三个参数来给我们提供更多的控制。在性能方面还有其他区别吗?没有。如果代码中的瓶颈变成了使用class语句调用类型之间的区别,恭喜你编写了一些速度惊人的代码。因此,基本上第一个语法通过让我们构造元类的第一个和第三个参数,为我们提供了更多的控制。在性能方面还有其他区别吗?没有。如果代码中的瓶颈成为使用class语句和调用type之间的区别,那么恭喜你编写了速度惊人的代码。我以前使用过第二种模式,但很少使用。正如其他一些答案所述,直接使用类型提供了最大的灵活性。例如,如果您希望能够计算必须使用类型的类的名称;类似地,如果类主体是以某种方式计算的,甚至是它的基类。我以前使用过第二种模式,但很少使用。正如其他一些答案所述,直接使用类型提供了最大的灵活性。例如,如果您希望能够计算必须使用类型的类的名称;类似地,如果类主体是以某种方式计算的,甚至是它的基类。