繁体   English   中英

动态创建一个类而不实例化它 - 没有元类?

[英]Create a class dynamically without instantiating it - no metaclasses?

使用WTForms表单定义类作为示例:

class RegistrationForm(Form):
    username     = StringField('Username', [validators.Length(min=4, max=25)])
    email        = StringField('Email Address', [validators.Length(min=6, max=35)])
    accept_rules = BooleanField('I accept the site rules', [validators.InputRequired()])

并查看库的源似乎WTForms允许用户定义一个非常简单的类定制形式结构的(如上),这反过来又然后被用于构造实例化的新的字段类当类是产生。

我已经阅读了许多关于类工厂和元类的教程,一般的共识是避免使用元类并使用类装饰器之类的东西。 问题是教程要么开始导入额外的库,例如: import six ,将不同Python版本的解释混合在一起,使用过于复杂的示例或建议不要使用元类。

有人可以提供一个非常简单的解释(对于Python 3),如何使用简单的类定义(如上面的WTForms示例)和元类来定制类的全新构造,而无需在构造时实际实例化类。

编辑:道歉发现很难解释我的最终目标是什么但是因为我已经完成了教程,不清楚类装饰器,元类,魔术方法( 调用新建初始化 )或其组合是什么我需要实现我想象的东西,或者我可视化的东西是错误的做事方式。 不幸的是,如果不能理解实现它所需的机制,似乎无法判断我的目标是否错误。 我已经意识到元类是要走的路,只需要指向一个非常简单的元类例子来完成Python 3.x方式。

您可以动态创建类 - 没有自定义元类,也没有装饰器,而程序员看起来就是简单的函数调用。

只需使用三个参数调用Python的内置type :类的名称,带有基数的元组,以及带有其名称空间的映射对象(即包含通常在类主体上定义的属性和方法的字典)。

def __init__(self):
    ...

namespace = {
   '__init__': init,
   'name': 'default name'
}

MyClass = type("MyClass", (object,), namespace)

你放弃了一些只有可能的功能,因为编译器在构建类体内声明的函数期间做了一些特殊的事情 - 主要是能够使用以__开头的无参数super和名称重命名的属性,但就是这样。

那说应该注意这不是“没有元类”。 “type”本身就是一个元类 - 所有对象的默认Python元类 - 并且正在调用一个创建类的元类。 没有其他方法可以创建一个类。 “类装饰器”只是一种可以在创建类对象后对其进行更改的方法。

产生新的动态类的任何函数或方法都会在其中包含调用type或其他元类。 同样的情绪,“元类”本身不会创建动态类 - 它需要在类体声明中使用,或者使用(至少)与调用type相同的参数调用。

至于“类装饰器”而不是元类的建议,我不确定是真的(除了“类装饰器”没有办法可以自动动态创建类):它们的主要缺点是没有普通的装饰类的子类使父类的类装饰器自动应用于自身的方式,同时继承元类。

在Python 3.6中你有__init_subclass__协议,是的,它可以避免很多传统的元类使用(但它仍然不会“动态创建类” - 调用type就是这样)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM