0

I want to set class property dynamicly. I do it like this:

class Foo:
    def __init__(self):
        self.a = 1


for v in [1, 2, 3]:
    setattr(Foo, f"test_{v}", property(lambda self: self.a + v))

foo = Foo()
print(foo.test_1)
print(foo.test_2)
print(foo.test_3)

but I find that this will return the same result.

roger
  • 9,063
  • 20
  • 72
  • 119

2 Answers2

0

The signature for setattr is setattr(object, name, value)

class Foo:
    pass


for v in [1, 2, 3]:
    setattr(Foo, f"test_{v}", v)

foo = Foo()
print(foo.test_1)
print(foo.test_2)
print(foo.test_3)

Output:

1
2
3

Edit: 1

If becomes very easy if you set the property to the objects instead

class Foo:
    def __init__(self, a=1):
        self.a = a
        for v in [1, 2, 3]:
          setattr(self, f"test_{v}", self.a + v )

foo = Foo()
print(foo.test_1, foo.test_2, foo.test_3)
foo = Foo(10)
print(foo.test_1, foo.test_2, foo.test_3)

Output:

2 3 4
11 12 13

But, if you want to set it at class level, then answer by @nlair is closes.

mujjiga
  • 16,186
  • 2
  • 33
  • 51
0

You need to force the evaluation of v. You can use partial from functools. I am not sure it is very clean but it does what you are looking for.

from functools import partial

class Foo:
    def __init__(self):
        self.a = 1


for v in [1, 2, 3]:
    def aux(obj,x):
        return obj.a + x
    setattr(Foo, f"test_{v}", property(partial(aux,x=v))

foo = Foo()
print(foo.test_1)
print(foo.test_2)
print(foo.test_3)

Output:

2
3
4
nlair
  • 101
  • 2