By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
443,627 Members | 2,339 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 443,627 IT Pros & Developers. It's quick & easy.

"once" assigment in Python

P: n/a
Hello,

I've been using Python for some DES simulations because we don't need
full C speed and it's so much faster for writing models. During
coding I find it handy to assign a variable *unless it has been
already assigned*: I've found that this is often referred to as "once"
assigment.

The best I could come up with in Python is:

try:
variable
except NameError:
variable = method()

I wonder if sombody has a solution (trick, whatever ...) which looks
more compact in coding. Something like:

once(variable, method)

doesn't work, but it would be perfect. Of course I can preprocess the
Python code but an all-Python solution would be more handy.

Any suggestions?

Thx in advance,
Lorenzo

Sep 14 '07 #1
Share this Question
Share on Google+
10 Replies


P: n/a
In message <11*********************@w3g2000hsg.googlegroups.c om>, Lorenzo Di
Gregorio wrote:
During coding I find it handy to assign a variable *unless it has been
already assigned*: I've found that this is often referred to as "once"
assigment.
Why not just assign to it once at the beginning and be done with it?
Sep 14 '07 #2

P: n/a
Lorenzo Di Gregorio wrote:
Hello,

I've been using Python for some DES simulations because we don't need
full C speed and it's so much faster for writing models. During
coding I find it handy to assign a variable *unless it has been
already assigned*: I've found that this is often referred to as "once"
assigment.

The best I could come up with in Python is:

try:
variable
except NameError:
variable = method()

I wonder if sombody has a solution (trick, whatever ...) which looks
more compact in coding. Something like:

once(variable, method)

doesn't work, but it would be perfect. Of course I can preprocess the
Python code but an all-Python solution would be more handy.

Any suggestions?
Without being fatuous, I would suggest you rethink your approach to the
problem.

Do your variables have default values? If not, what happens if the user
does not set them and your code tries to refer to them? You seem to be
trying to apply defaults if the user hasn't set a value, when the
correct things to do is to apply the defaults *before the user gets a
chance to do anything at all*. Then any changes made by the user will
overwrite the defaults.

Even better, if its practical, is to provide your functionality as one
or more functions, whose definitions can set default values for keyword
arguments.

regards
Steve
--
Steve Holden +1 571 484 6266 +1 800 494 3119
Holden Web LLC/Ltd http://www.holdenweb.com
Skype: holdenweb http://del.icio.us/steve.holden

Sorry, the dog ate my .sigline

Sep 14 '07 #3

P: n/a
Lorenzo Di Gregorio wrote:
I've been using Python for some DES simulations because we don't need
full C speed and it's so much faster for writing models. During
coding I find it handy to assign a variable *unless it has been
already assigned*: I've found that this is often referred to as "once"
assigment.

The best I could come up with in Python is:

try:
variable
except NameError:
variable = method()

I wonder if sombody has a solution (trick, whatever ...) which looks
more compact in coding. Something like:

once(variable, method)

doesn't work, but it would be perfect. Of course I can preprocess the
Python code but an all-Python solution would be more handy.

Any suggestions?
You can use properties to implement lazy evaluation. Or you can rely on a
naming convention:
>>class Once(object):
.... def __getattr__(self, name):
.... if name.startswith("_calc_"):
.... raise AttributeError("No method to calculate attribute %r" % name[6:])
.... value = getattr(self, "_calc_" + name)()
.... setattr(self, name, value)
.... return value
....
>>class A(Once):
.... def _calc_foo(self):
.... print "calculating foo"
.... return 42
....
>>a = A()
a.foo
calculating foo
42
>>a.foo
42
>>a.bar
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 5, in __getattr__
File "<stdin>", line 4, in __getattr__
AttributeError: No method to calculate attribute 'bar'
>>a._calc_bar = lambda: "bar-value"
a.bar
'bar-value'

Peter
Sep 14 '07 #4

P: n/a
Agree that what you are looking for may not be a good idea. So make
sure you don't shoot yourself in the foot with it. You should
probably look into your problem some more.
>>def once(obj,attrname,value):
.... if hasattr(obj,attrname):
.... return
.... else:
.... setattr(obj,attrname,value)
....
>>class Foo:
.... pass
....
>>foo = Foo()
once(foo,"a",1)
foo.a
1
>>once(foo,"b",2)
foo.a
1
>>def m1(self):
.... print "i am m1"
....
>>def m2(self):
.... print "i am m2"
....
>>once(Foo,"mx",m1)
foo.mx()
i am m1
>>once(Foo,"mx",m2)
foo.mx()
i am m1
>>>
This is very generic code, but you could make it specific to a class
and an attribute. If so look into properties.

class Foo2:

def _setMyAttr(self,value):
if hasattr(self,"_myAttr"):
return
self._myAttr = value

def _getMyAttr(self):
if not hasattr(self,"_myAttr"):
return "somedefaultvalue"
return self._myAttr

myAttr = property(_getMyAttr,_setMyAttr)

Note also : stay away from __setattr__ until you know what you are
doing and
you know when to use self.__dict__ assignments. Painful personal
experiences for me.

Sep 14 '07 #5

P: n/a
On Fri, 14 Sep 2007 06:16:56 +0000, Lorenzo Di Gregorio wrote:
Hello,

I've been using Python for some DES simulations because we don't need
full C speed and it's so much faster for writing models. During coding
I find it handy to assign a variable *unless it has been already
assigned*: I've found that this is often referred to as "once"
assigment.
I could see reasons for doing something like this at a module level or
for attributes; such as setting default values when defaults are
expensive to calculate. You could, as others have said, initialize the
variable to a trivial value and then test whether it still held the
trivial value later, but what's the point?

The best I could come up with in Python is:

try:
variable
except NameError:
variable = method()

I wonder if sombody has a solution (trick, whatever ...) which looks
more compact in coding. Something like:

once(variable, method)

doesn't work, but it would be perfect.
For module level variables you can do something like this:

def once(symbol,method):
g = globals()
if symbol not in g:
g[symbol] = method()

You'd have to pass a symbol as a string, but that's no big deal.

For local variables you're stuck with trying to catch UnboundLocalError.
There's a way to do it by examining stack frames, but I don't really
recommend it: it's inefficient, and the once assignment doesn't make as
much sense for local variables.

Carl Banks
Sep 14 '07 #6

P: n/a
Thank you very much for your suggestions!
I'll try in the next days to elaborate a bit on the last two ones.

By the way, the "once" assignment is not that evil if you use it for
hardware modeling.
Most hardware models look like:

wire1 = function()
instance component(input=wire1,output=wire2)
result = function(wire2)

When employing Python it's pretty straightforward to translate the
instance to an object.

instance = Component(input=wire1,output=wire2)

Then you don't use "instance" *almost* anymore: it's an object which
gets registered with the simulator kernel and gets called by reference
and event-driven only by the simulator kernel. We might reuse the
name for calling some administrative methods related to the instance
(e.g. for reporting) but that's a pretty safe thing to do. Of course
all this can be done during initialization, but there are some good
reasons (see Verilog vs VHDL) why it's handy do be able to do it
*anywhere*. The annoying problem was that every time the program flow
goes over the assignment, the object gets recreated.

Indeed Python itself is not a hardware modeling language, but I built
some infrastructure to fill what I was missing and for quickly
building up a functional prototype and testing some ideas Python is
really excellent.

Best Regards,
Lorenzo

Sep 14 '07 #7

P: n/a
Lorenzo Di Gregorio <lo****************@gmail.comwrote:
When employing Python it's pretty straightforward to translate the
instance to an object.

instance = Component(input=wire1,output=wire2)

Then you don't use "instance" *almost* anymore: it's an object which
gets registered with the simulator kernel and gets called by reference
and event-driven only by the simulator kernel. We might reuse the
name for calling some administrative methods related to the instance
(e.g. for reporting) but that's a pretty safe thing to do. Of course
all this can be done during initialization, but there are some good
reasons (see Verilog vs VHDL) why it's handy do be able to do it
*anywhere*. The annoying problem was that every time the program flow
goes over the assignment, the object gets recreated.
If you originally set, e.g.,

instance = None

then using in your later code:

instance = instance or Component(...)

will stop the multiple creations. Other possibilities include using a
compound name (say an.instance where 'an' is an instance of a suitable
container class) and overriding the __new__ method of class Component so
that it will not return multiple distinct objects with identical
attributes. "Has this *plain* name ever been previously assigned to
anything at all" is simply not a particularly good condition to test for
(you COULD probably write a decorator that ensures that all
uninitialized local variables of a function are instead initialized to
None, but I'd DEFINITELY advise against such "black magic").
Alex
Sep 14 '07 #8

P: n/a
Lorenzo Di Gregorio wrote:
Hello,

I've been using Python for some DES simulations because we don't need
full C speed and it's so much faster for writing models. During
coding I find it handy to assign a variable *unless it has been
already assigned*: I've found that this is often referred to as "once"
assigment.

The best I could come up with in Python is:

try:
variable
except NameError:
variable = method()

I wonder if sombody has a solution (trick, whatever ...) which looks
more compact in coding. Something like:

once(variable, method)

doesn't work, but it would be perfect. Of course I can preprocess the
Python code but an all-Python solution would be more handy.

Any suggestions?

Thx in advance,
Lorenzo
IMHO variables like what you describe are really data not program variables.
You might consider putting variables like these in a dictionary and then check
to see if the keys exist before assignment:

var_dict={}

#
# See if 'varname' initialized, if not it needs to be
#
if 'varname' not in var_dict:
var_dict[varname]=somevalue

-Larry
Sep 17 '07 #9

P: n/a
On 17 Sep., 16:54, Larry Bates <larry.ba...@websafe.comwrote:
>
IMHO variables like what you describe are really data not program variables.
You might consider putting variables like these in a dictionary and then check
to see if the keys exist before assignment:

var_dict={}

#
# See if 'varname' initialized, if not it needs to be
#
if 'varname' not in var_dict:
var_dict[varname]=somevalue
This is a good point!

I could write something like:

instantiate('component',function)

and have instantiate() to conditionally do:

instance['component']=Module(function)

Of course this means using:

instance['component'].method()

instead of just:

component.method()

A more annoying difficulty is with the fact that, while the scope of
ordinary variables is limited (function, package), the scope of
'component' would be global (the whole instance[]): having global
names could be pretty annoying in modeling a hierarchy. Anyway, some
scoping mechanism could be implemented over the global dictionary and
this could be a good price to pay to avoid other tricks.
Further suggestions?

Thank you!
Lorenzo

Sep 17 '07 #10

P: n/a
Lorenzo Di Gregorio wrote:
On 17 Sep., 16:54, Larry Bates <larry.ba...@websafe.comwrote:
>IMHO variables like what you describe are really data not program variables.
You might consider putting variables like these in a dictionary and then check
to see if the keys exist before assignment:

var_dict={}

#
# See if 'varname' initialized, if not it needs to be
#
if 'varname' not in var_dict:
var_dict[varname]=somevalue

This is a good point!

I could write something like:

instantiate('component',function)

and have instantiate() to conditionally do:

instance['component']=Module(function)

Of course this means using:

instance['component'].method()

instead of just:

component.method()
Well, you could do that. Or you could define a class, with a __getattr__
that returns the required default value in the case where no setting had
been made.

Then you can assign components (with their own hierarchies) to the
attributes of your top-level design ...
A more annoying difficulty is with the fact that, while the scope of
ordinary variables is limited (function, package), the scope of
'component' would be global (the whole instance[]): having global
names could be pretty annoying in modeling a hierarchy. Anyway, some
scoping mechanism could be implemented over the global dictionary and
this could be a good price to pay to avoid other tricks.
Further suggestions?
It's not actually that hard to create objects that allow you to access
their attributes using *either* attribute or indexing notation.

regards
Steve
--
Steve Holden +1 571 484 6266 +1 800 494 3119
Holden Web LLC/Ltd http://www.holdenweb.com
Skype: holdenweb http://del.icio.us/steve.holden

Sorry, the dog ate my .sigline

Sep 18 '07 #11

This discussion thread is closed

Replies have been disabled for this discussion.