以编程方式定义类:type vs types.new_class

Car*_*nta 7 python

除了types.new_class在创建类时定义关键字参数的能力.这两种方法之间是否存在重大差异?

import types

First = type('First',(object,),{'asd':99})
k = First()

Second = types.new_class('Second',(object,),{},lambda x:x)
x = Second()
Run Code Online (Sandbox Code Playgroud)

tim*_*ree 6

这两种方法之间有什么主要区别吗?

是的。答案涉及一个称为“元类”的概念。

[元类] 是比 99% 的用户应该担心的更深层次的魔法。如果您想知道是否需要它们,则不需要(真正需要它们的人肯定知道他们需要它们,并且不需要解释原因)。? Tim Peters,Python Zen of Python 的作者(来源

如果您认为自己已经达到了 99%,那么就不要再读下去了,可以随意使用type. types.new_class除了在您使用元类的罕见情况下,它也一样好。

如果您想了解有关元类的更多信息,我建议您查看发布在“ Python 中的元类是什么? ”的一些高质量答案。(我推荐这个。)

一旦你理解了元类是什么,答案就显而易见了。由于type是一个特定的元类,因此只有当您想创建将其用作元类的类时,它才会起作用。

但是,如果您想使用非默认元类

class MySimpleMeta(type):
    pass
Run Code Online (Sandbox Code Playgroud)

和静态类不会做

class MyStaticClass(object, metaclass=MySimpleMeta):
    pass
Run Code Online (Sandbox Code Playgroud)

然后你可以使用 types.new_class

import types

MyStaticClass = types.new_class("MyStaticClass", (object,), {"metaclass": MyMeta}, lambda ns: ns)
# this is equivalent to the above class.
Run Code Online (Sandbox Code Playgroud)

(顺便说一句,它需要一个可调用的(例如lambda ns: ns)而不是字典的原因因为元类可以关心定义属性的顺序。

  • 除此之外,您已经可以使用静态已知元类(正如您所指出的)动态创建一个新类,例如`MyStaticClass = MySimpleMeta("MyStaticClass", (), {})`。new_class 的优点是它允许动态确定元类本身。 (3认同)

Ang*_*nds 3

我意识到这已经晚了,因此您可能已经自己回答了这个问题。

首先,你似乎误解kwdstypes.new_class;它是类关键字参数,例如

class MyMeta(type):
    def __new__(metacls, name, bases, attrs, **config):
        print(config)
        return super().__new__(metacls, name, bases, attrs)

    def __init__(cls, name, bases, attrs, **config):
        super().__init__(name, bases, attrs)

class SomeCls(metaclass=MyMeta, debug=True):
    pass

>> {'debug': True}
Run Code Online (Sandbox Code Playgroud)

类似于(没有打印)

SomeCls = types.new_class("SomeCls", (), {'debug':True})
Run Code Online (Sandbox Code Playgroud)

这些元参数在配置元类时非常有用。

我不太确定为什么new_class设计为直接接受可调用与字典,但我怀疑这是为了避免不相互继承的“新”类之间的隐式共享状态。