yet another modifying locals() question

Steven D'Aprano steven at REMOVE.THIS.cybersource.com.au
Sun Sep 13 23:15:14 EDT 2009


On 2009年9月13日 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

AltStyle によって変換されたページ (->オリジナル) /