[Edu-sig] Python for Fun
Dethe Elza
delza@alliances.org
Fri, 25 May 2001 21:10:04 -0700
Hi Chris
> We're still on Python 1.5.3 mainly because we have so much code in
> running systems that upgrading involves a lot of regression
> testing. Try for this summer for sure. Lots of stuff out there that
> assumes 2.0 as a base. Zope, Vpython, wxPython, etc. A year ago we
> upgraded from 3.0 and had some glitches - mostly with comparisons
> where one value was None.
Actually, Zope still uses Python 1.5.x for much the same reasons: lots of
code to evaluate. The next release will be for 2.0, I think. Likewise,
wxPython and VPython were running on 1.5 until recently, so there should
either be a 1.5 branch of the current version, or an older install which
will work for you to play with. RedHat Linux (and others, I'm sure) still
seems to be shipping/using 1.5 (RedHat uses Python for their installer and
lots of utilities), and it has a tremendous installed base, so lots of folks
still support it in their tools.
>> Just for fun: tweaking logic.py Connector class with 2.1 idioms:
>>
>> def connect (self, inputs) :
>> if type(inputs) != type([]) : inputs = [inputs]
>> self.connects += inputs # <-- here
>>
> This is a nice new feature (+= etc.). Does it save time and
> evaluate the left hand address only once? Or is it just syntactic
> sugar? If the calculation is complex, it can make a real difference
> in program speed. Like
>
> array[n][nextSlot(whatever)] += 1
> Or in our case we are very often incrementing (or the like) an
> object attribute, which is a really a dict lookup. Don't want to do
> the lookup twice.
Augmented assignments ( x += y instead of x = x + y, etc.) were done as part
of PEP 203 (Python Enhancement Proposal), and according to that the
left-hand side is indeed evaluated only once.
http://python.sourceforge.net/peps/pep-0203.html
>> def set (self, value) :
>> if self.value == value : return # Ignore if no change
>> self.value = value
>> if self.activates : self.owner.evaluate()
>> if self.monitor :
>> print "Connector %s-%s set to %s" % \
>> (self.owner.name,self.name,self.value)
>> [con.set(value) for con in self.connects] # <-- and here
>>
> This should also save time, I would think, since the list is not
> constantly resized? Can't test it. Don't work on 1.5.3
Not sure what the issue is here.
>> Could also go:
>>
>> self.connects.extend(inputs) (is that 1.5 or later?)
>>
> Is this actually different from .append ?
I believe extend adds a list to a list, making a list which is the union.
Append would take the additional list and make it a single node of the first
list (lengthening by one rather than by the length of the added list).
>> I find it interesting that you can define lists simply for
>> their side-effects, with the list itself saved nowhere. Indeed,
>> you can stick [1,2,3] (no assignment to a variable) anywhere
>> a method and nothing happens -- __repr__ isn't triggered
>> except at the command line.
>>
> That's kind of cool. I had never tried it. Replace 1,2,3 with
> function calls and off they go, left to right. This reminds me of
> the old Lisp "PROG" that would evaluate its arguments just for the
> side effects.
>
>> I did have
>>
>> map(lambda con: con.set(value), self.connects)
>>
>> which makes use of nested scopes (value in lambda is getting a
>> pointer from the surrounding method), but list comprehension
>> doesn't see this as a case of scope nesting i.e. variables
>> within the brackets are locally scoped already.
>>
>
> I tried this and it seemed to work
>>>>
>>>> class con :
> ... def __init__ (self) :
> ... self.x = 5
> ... def prnt (selfi,c) :
> ... print self.x + c
> ...
>>>> a = con()
>>>> b = [a,a,a]
>>>> map(lambda x: x.prnt(4), b)
> 9
> 9
> 9
> [None, None, None]
>>>>
> Speaking of scoping. If you get around to Lisp in Python, there's a
> section on dynamic scoping with an example.
>
> Chris
>
--
Dethe Elza
Chief Mad Scientist
Burning Tiger Technologies