动态创建类属性 [英] creating class properties dynamically
问题描述
我正在寻找一种动态创建具有可通过典型实例符号访问的特定属性的类的方法.
I am looking for a way to dynamically create classes with specific properties accessible via typical instance notation.
DynoOne = createClass('DynoOne',props=['A','B'])
d = DynoOne (database='XYZ')
d.A = d.B + 1
DynoTwo = createClass('DynoTwo',props=['A','C','E'])
q = DynoTwo (database='QRS')
q.A = q.C + 2*q.E
有关道具"实际获取和修改方式的详细信息将被隐藏.当新道具可用时,这也使添加新道具的访问变得更加容易.
Details of how the "props" are actually acquired and modified would be hidden. This also makes it easier to add access to new props as they become available.
我已经尝试了以下技术,以了解python如何动态产生基本的类属性:
I have experimented with techniques such as the following, to get a feel for how python can dynamically produce basic class attributes:
我最初对python的阅读表明,类属性是处理引入getter/setter方法进行访问的一种方法.
My initial reading on python suggests that class properties are one way to handle introducing getter/setter methods for access.
尚不清楚的是如何在工厂构造函数方法中动态指定属性名称(无论使用装饰器还是显式的property()调用)
What's not clear is how to dynamically specify property names in the factory constructor method (whether using decorators or explicit property() call)
例如,使用property()...
E.g., using property() . . .
class DynamicClass( someBase ):
def dynamic_getter(self):
# acquire "stuff"
return stuff
def dynamic_setter(self,stuff):
# store "stuff"
pass
dynamic_property_name = property(fget=dynamic_getter,fset=dynamic_setter)
当类被声明/构造时,我需要为每个请求的道具创建一个集合.例如,DynoOne类将为"A"和"B"分别设置属性/设置器/获取器.
When the class is declared/constructed, I need to create a set per requested prop. E.g., the DynoOne class would have separate property/setter/getter for 'A' and 'B'.
我怀疑基于模板的eval()策略是可行的,但我可能会缺少一些更基本,更有效的技术.
I suspect that a template-based eval() strategy would work, but I am likely missing some more fundamental and effective technique.
很感谢启发和学习机会:-)
Enlightenment and learning opportunities are appreciated :-)
推荐答案
type
的三个参数使您可以动态创建类.因此,一个草图:
The three-argument for of type
lets you create classes dynamically. So, a sketch:
def dynamic_getter(self):
# acquire "stuff"
return stuff
def dynamic_setter(self,stuff):
# store "stuff"
pass
DynamicClass = type('DynamicClass', (SomeBase,), {"dynamic_property_name":property(fget=dynamic_getter,fset=dynamic_setter)})
或更具体地说:
In [1]: class SomeBase:
...: def __init__(self):
...: self._foo = 42
...:
...: def dynamic_getter(self):
...: # acquire "stuff"
...: return self._foo
...:
...: def dynamic_setter(self,stuff):
...: # store "stuff"
...: pass
...:
...: DynamicClass = type('DynamicClass', (SomeBase,), {"dynamic_property_name":property(fget=dynamic_getter,fset=dynamic_setter)})
In [2]: instance = DynamicClass()
In [3]: instance.dynamic_property_name
Out[3]: 42
注意: type
实际上是一个与其他任何对象一样的类对象,并且以三参数形式对其进行调用是新类对象实例的构造函数,它是创建其他类对象的类,即一个元类.确实,您可以将类定义语句视为上述的语法糖.
Note: type
is literally a class object like any other, and calling it in it's three-argument form is a constructor for new class object instances, it is the class that creates other class objects, i.e. a metaclass. Indeed, you can think of a class definition statement as syntactic sugar for the above.
基于模板的 exec
(如果要使用复杂的语句,则需要 exec
, eval
仅允许表达式)的方法也是可行的,如果您发现更容易使用的话.确实,这就是 collections.namedtuple
在标准库中的工作方式.
A template-based with exec
(if you want to use a complex statement, you'd need exec
, eval
only allows expressions) approach is also viable, if you find that easier to work with. Indeed, that is how collections.namedtuple
works in the standard library.
注意:您似乎对Python属性的性质感到困惑.没有在类上指定实例属性,相反,您将添加一个用于初始化这些实例属性的函数(通常为 __ init __
),但您可以在任意位置添加实例属性,甚至在外部方法/类.
Note: you seem to be confused about the nature of properties in Python. Instance attribtus are not specified on the class, rather, you'd add a function that initializes those instance attributes (typically __init__
) but you can add instance attributes anywhere, even outside of a method/class.
这篇关于动态创建类属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!