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

时间:2016-12-19 02:45:32

标签: 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()

2 个答案:

答案 0 :(得分:2)

两种方法之间是否有主要区别?

。答案涉及一个称为“ metaclasses”的概念。

  

[Metaclasses]比99%的用户应有的魔力深   永远担心。如果您想知道是否需要它们,则不需要   实际需要他们的人肯定知道他们需要他们,并且   不需要解释为什么)。 ⸺Tim Peters,Python的Zen(source)的作者

如果您认为自己处于99%的水平,则无需进一步阅读,可以随时使用type。除了在极少数情况下使用元类的情况之外,它与types.new_class一样好。

如果您想了解有关元类的更多信息,建议您查看发布到“ What are metaclasses in Python?”的一些高质量答案。(我建议this one

一旦理解了元类是什么,答案就很不言而喻了。由于type是特定的元类,因此只有在要创建将其用作其元类的类时,它才有效。

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

class MySimpleMeta(type):
    pass

静态类不会

class MyStaticClass(object, metaclass=MySimpleMeta):
    pass

然后您可以使用types.new_class

import types

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

(简单地说,它需要可调用(例如lambda ns: ns)而不是字典的原因是because metaclasses are allowed to care about the order in which the attributes are defined.

答案 1 :(得分:0)

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

首先,您似乎误解了kwds的{​​{1}}论点;它是类关键字参数,例如

types.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}

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

我不确定为什么SomeCls = types.new_class("SomeCls", (), {'debug':True}) 被设计为直接接受可调用vs dict,但我怀疑它是为了避免" new"之间的隐式共享状态。不相互继承的类。