6

I want to create a object with certain properties. I want to add them dynamically. Similar to Adding a Method to an Existing Object Instance, but then with properties instead of methods. A simple example follows.

I like to create dynamically:

class A():
    @property
    def a(self):
        return self._a
    @a.setter
    def a(self, x):
        self._a = 10*x

    @property
    def b(self):
        return self._b
    @b.setter
    def b(self, x):
        self._b = 10*x

To do this with methods, i would do:

class B():
    def __init__(self):
        for i in range(70,80):
            self.__dict__[chr(i)] = types.MethodType(lambda self,x: x*i, self)

For properties I tried:

class B():
    def __init__(self):
        for i in range(70,80):
            def tmp(self, x):
                self._x = i*x
            self.__dict__[chr(i)] = property(fget=lambda self: self._i, fset=tmp)

I also found the types.DynamicClassAttribute, but I am not sure if this will help.

A relevant question is asked here, about adding properties to a class (in python 2): Dynamically adding @property in python . I do not see how I can extend this to instances of a class.

Background

I want to write a "driver" for the lantz project to use a camera via the PyPylon wrapper. The camera has some properties, which are not known in advance. I want to add all properties as Feats (some decorator supplied by lantz, which looks similar to a property: it has a getter and a setter).

Edit: it look likes How to add property to a class dynamically? is the same question

Vasco
  • 1,177
  • 11
  • 28
  • 2
    https://stackoverflow.com/questions/17330160/how-does-the-property-decorator-work might be useful – Tom Dalton Jan 25 '18 at 16:53
  • Does this answer your question? [Dynamically adding @property in python](https://stackoverflow.com/questions/2954331/dynamically-adding-property-in-python) – YouJiacheng Dec 14 '22 at 21:26

1 Answers1

4

This comment gave a hint to the answer.

The follow function (inspired on 1) adds a property to a single instance of a class. It does it by creating a new class on the fly.

def attach_dyn_propr(instance, prop_name, propr):
    """Attach property proper to instance with name prop_name.

    Reference: 
      * https://stackoverflow.com/a/1355444/509706
      * https://stackoverflow.com/questions/48448074
    """
    class_name = instance.__class__.__name__ + 'Child'
    child_class = type(class_name, (instance.__class__,), {prop_name: propr})

    instance.__class__ = child_class

Example and test:

def getter(self): print('Get!')
def setter(self, value): print('Set to {!r}!'.format(value))
def deleter(self): print('Delete!')
prop = property(getter, fset=setter, fdel=deleter)

class Foo: pass
foo = Foo()
foo2 = Foo()
attach_dyn_propr(foo, 'p', prop)

foo.p
foo2.p

... Get
... AttributeError: 'Foo' object has no attribute 'p'
Vasco
  • 1,177
  • 11
  • 28