I agree with earlier respondents that it’s a bit strange to use properties here, but it is possible to do so and not really that difficult - if you remember that properties are descriptor objects that need to be defined on the class.
But on the other hand, properties do have the very nice feature that what looks like a simple attribute actually works like an arbitrary function (so in your cause you would not have to explicitly call “PlaySound” each time - this would be abstracted aways inside the property access).
For instance this works:
from functools import partial
def play(v, instance):
print("Play", v)
# or do other stuff
class X:
def __init__(self, **kwargs):
for k, v in kwargs.items():
setattr(X, k, property(partial(play, v)))
# note: you need partial, cannot use a lambda here
That’s quite a bit simpler than all the manipulations with getattr, eval, exec, imo.
Now you get
>>> x = X(a=1, b=2, c=3)
>>> x.a
Play 1
>>> x.b
Play 2
What is a bit strange here, imo, is that the initialization of on X object sneaks in some changes to its own class definition. So you also get
>>> x = X(a=1, b=2, c=3)
>>> y = X()
>>> y.a
Play 1
In your case, you may actually see this as a desirable feature. And Python allows this kind of crazy dynamic stuff, so…
There is a pretty nice, old blog post about Python properties and descriptors that you may also find interesting: Python FAQ: Descriptors / fuzzy notepad