Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   Python (http://www.velocityreviews.com/forums/f43-python.html)
-   -   yet another modifying locals() question (http://www.velocityreviews.com/forums/t698175-yet-another-modifying-locals-question.html)

Ed Anuff 09-14-2009 01:52 AM

yet another modifying locals() question
 
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:

>>> 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.

Is there a reason why this works and is it safe to rely on it or is
there a better approach? BTW, this works in a program too, it's not
just an artifact of the command line interpreter globals() = locals()
thing.

Thanks

Ed


Steven D'Aprano 09-14-2009 03:15 AM

Re: yet another modifying locals() question
 
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

Ed Anuff 09-14-2009 06:53 AM

Re: yet another modifying locals() question
 
On Sep 13, 8:15*pm, Steven D'Aprano
<ste...@REMOVE.THIS.cybersource.com.au> wrote:
> Metaclasses are left as an exercise for the reader.


The parent class has a metaclass, which is why I was trying this
approach instead, since it let me get at the class attributes before
the metaclass did. Overriding the metaclass looked to be a much more
messy proposition, but I think I've got that working now. Thanks


All times are GMT. The time now is 09:26 PM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.