creating class properties dynamically

北城余情 提交于 2021-02-08 14:10:56

问题


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.

I have experimented with techniques such as the following, to get a feel for how python can dynamically produce basic class attributes:

Class factory to produce simple struct-like classes?

My initial reading on python suggests that class properties are one way to handle introducing getter/setter methods for access.

What's not clear is how to dynamically specify property names in the factory constructor method (whether using decorators or explicit property() call)

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)

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'.

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 :-)


回答1:


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)})

Or, more concretely:

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

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.

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.

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.




回答2:


In python, instance variables are stored under a dict which can be used to create dynamic instance variables at the time of object creation of a class.

Let's say, I have a dict {'a':1} in which the key 'a' should be assigned as a variable and 1 as its value.

Under__init__ function, we can do like,

self.__dict__['a'] = 1 

We can use a for loop to iterate over the dictionary and do the above to create dynamic variables.

As per @chepner suggestion, we can also use setattr function to set variables dynamically.



来源:https://stackoverflow.com/questions/57811102/creating-class-properties-dynamically

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!