yet another modifying locals() question
Steven D'Aprano
steven at REMOVE.THIS.cybersource.com.au
Sun Sep 13 23:15:14 EDT 2009
On Sun, 13 Sep 2009 18:52:47 -0700, Ed Anuff wrote:
> I know that locals() is not supposed to be modifiable under most
> circumstances, but I'm trying to solve a situation where I'm dynamically
> generating some class attributes and it seemed to be the best way, so I
> tried something out that seems to work but I'm not sure that it's
> kosher:
Given that the docs state not to rely on modifying locals(), I think it
is safe to say it's NOT kosher. If it works for you, you're lucky, but it
might stop working in the future.
>>>> def f(l):
> ... l['b'] = 1
> ...
>>>> class A:
> ... f(locals())
> ...
>>>> A.b
> 1
> In my code, I'm doing something quite a bit more complex than just
> assigning a single attribute, but this is the simplest use case example.
If you want to dynamically assign attributes after the class is created,
setattr() is your friend:
class A:
pass
setattr(A, 'b', 1) # set a class attribute
With full knowledge of the risks of exec'ing untrusted data, you can use
exec:
class A:
exec('b = 1')
For advanced use, you can look at class decorators and metaclasses.
def decorator(cls):
# Add a class attribute b to the cls.
cls.b = 1
return cls
@decorator
class A:
pass
The above @ syntax requires Python 2.6 or better, but in older versions
you can write:
class A:
pass
A = decorator(A)
To make it even more dynamic, write a decorator factory:
def decorator(name):
def inner(cls):
setattr(cls, name, 1)
return cls
return inner
class A:
pass
A = decorator('b')(A)
Metaclasses are left as an exercise for the reader.
--
Steven
More information about the Python-list
mailing list