动态创建类属性

时间:2019-09-05 18:23:34

标签: python python-3.x class metaprogramming

我正在寻找一种动态创建具有可通过典型实例符号访问的特定属性的类的方法。

       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

有关“道具”实际获取和修改方式的详细信息将被隐藏。 当新道具可用时,这也使添加新道具的访问变得更加容易。

我已经尝试了以下技术,以了解python如何动态产生基本的类属性:

Class factory to produce simple struct-like classes?

我最初对python的阅读表明,类属性是处理引入getter / setter方法进行访问的一种方法。

尚不清楚的是如何在工厂构造函数方法中动态指定属性名称(无论使用装饰器还是显式的property()调用)

例如,使用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”分别设置属性/设置器/获取器。

我怀疑基于模板的eval()策略是可行的,但我可能会缺少一些更基本和有效的技术。

赞赏和学习机会:-)

2 个答案:

答案 0 :(得分:4)

type的三个参数使您可以动态创建类。因此,一个草图:

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实际上是一个与其他任何对象一样的类对象,并且以三参数形式对其进行调用是新类对象实例的构造函数,它是创建其他类对象的类,即元类。确实,您可以将类定义语句视为上述的语法糖。

基于模板的exec(如果您想使用复杂的语句,则需要execeval仅允许表达式),如果您发现更容易使用。实际上,collections.namedtuple就是在标准库中的工作方式。

注意:您似乎对Python属性的性质感到困惑。没有在类上指定实例属性,而是添加了一个初始化那些实例属性(通常为__init__)的函数,但是即使在方法之外,也可以在任意位置添加实例属性 / class。

答案 1 :(得分:0)

在python中,实例变量存储在dict下,该类可在创建类的对象时用于创建动态实例变量。

比方说,我有一个字典{'a':1},其中将键'a'分配为变量,并将值1分配为变量。

__init__功能下,我们可以做到

self.__dict__['a'] = 1 

我们可以使用for循环遍历字典并执行上述操作以创建动态变量。

根据@chepner的建议,我们还可以使用setattr函数动态设置变量。