Dr. Dobb's Python-URL! - weekly Python news and links (Dec 7)

C

Cameron Laird

QOTW: "... and to my utter surprise it worked." - Andrew Nagel on
his move from wxPython to programming Tkinter in desperation

"Python has more web application frameworks than keywords." - Skip
Montanaro (but probably others going back years)


Frithiof Andreas Jensen writes frankly on use of SNMP and netconf:
http://groups.google.com/group/comp.lang.python/msg/662032bf92670fd7

Perhaps your application needs something like "ping". Several
distinct ways to achieve that exist:
http://groups.google.com/group/comp.lang.python/browse_thread/thread/ced60d60b5942f1f/

You're going to hear about reddit.com, and about how it's been
REimplemented in Python. Here's a fraction of the commentary:
http://reddit.com/blog/2005/12/night-of-living-python.html
http://www.aaronsw.com/weblog/rewritingreddit

Long discussions about Python documentation lead to no conclusion
this commentator knows how to summarize:
http://groups.google.com/group/comp.lang.python/browse_thread/thread/767470cb3cbc24d5/
http://groups.google.com/group/comp.lang.python/browse_thread/thread/94e2e5244a90a274/

aum's pygene genetic-algorithm solver "includes full api
documentation, and an implementation of the travelling
salesman problem ...":
http://groups.google.com/group/comp.lang.python/browse_thread/thread/9901fe0f886893d6/

Jibes against the lambda-clingers lead eventually to serious
questions of style in regard to variable namespacing,
lifespan, cleanup, and so on:
http://groups.google.com/group/comp.lang.python/browse_thread/thread/ad0e15cb6b8f2c32/

To say anything useful about IDEs apart from that one needs to
try each on for personal fit seems *very* difficult:
http://groups.google.com/group/comp.lang.python/browse_thread/thread/eca26b6e6617a591/


========================================================================
Everything Python-related you want is probably one or two clicks away in
these pages:

Python.org's Python Language Website is the traditional
center of Pythonia
http://www.python.org
Notice especially the master FAQ
http://www.python.org/doc/FAQ.html

PythonWare complements the digest you're reading with the
marvelous daily python url
http://www.pythonware.com/daily
Mygale is a news-gathering webcrawler that specializes in (new)
World-Wide Web articles related to Python.
http://www.awaretek.com/nowak/mygale.html
While cosmetically similar, Mygale and the Daily Python-URL
are utterly different in their technologies and generally in
their results.

For far, FAR more Python reading than any one mind should
absorb, much of it quite interesting, several pages index
much of the universe of Pybloggers.
http://lowlife.jp/cgi-bin/moin.cgi/PythonProgrammersWeblog
http://www.planetpython.org/
http://mechanicalcat.net/pyblagg.html

comp.lang.python.announce announces new Python software. Be
sure to scan this newsgroup weekly.
http://groups.google.com/groups?oi=djq&as_ugroup=comp.lang.python.announce

Steve Bethard, Tim Lesher, and Tony Meyer continue the marvelous
tradition early borne by Andrew Kuchling, Michael Hudson and Brett
Cannon of intelligently summarizing action on the python-dev mailing
list once every other week.
http://www.python.org/dev/summary/

The Python Package Index catalogues packages.
http://www.python.org/pypi/

The somewhat older Vaults of Parnassus ambitiously collects references
to all sorts of Python resources.
http://www.vex.net/~x/parnassus/

Much of Python's real work takes place on Special-Interest Group
mailing lists
http://www.python.org/sigs/

Python Success Stories--from air-traffic control to on-line
match-making--can inspire you or decision-makers to whom you're
subject with a vision of what the language makes practical.
http://www.pythonology.com/success

The Python Software Foundation (PSF) has replaced the Python
Consortium as an independent nexus of activity. It has official
responsibility for Python's development and maintenance.
http://www.python.org/psf/
Among the ways you can support PSF is with a donation.
http://www.python.org/psf/donate.html

Kurt B. Kaiser publishes a weekly report on faults and patches.
http://www.google.com/groups?as_usubject=weekly python patch

Cetus collects Python hyperlinks.
http://www.cetus-links.org/oo_python.html

Python FAQTS
http://python.faqts.com/

The Cookbook is a collaborative effort to capture useful and
interesting recipes.
http://aspn.activestate.com/ASPN/Cookbook/Python

Among several Python-oriented RSS/RDF feeds available are
http://www.python.org/channews.rdf
http://bootleg-rss.g-blog.net/pythonware_com_daily.pcgi
http://python.de/backend.php
For more, see
http://www.syndic8.com/feedlist.php?ShowMatch=python&ShowStatus=all
The old Python "To-Do List" now lives principally in a
SourceForge reincarnation.
http://sourceforge.net/tracker/?atid=355470&group_id=5470&func=browse
http://python.sourceforge.net/peps/pep-0042.html

The online Python Journal is posted at pythonjournal.cognizor.com.
(e-mail address removed) and (e-mail address removed)
welcome submission of material that helps people's understanding
of Python use, and offer Web presentation of your work.

del.icio.us presents an intriguing approach to reference commentary.
It already aggregates quite a bit of Python intelligence.
http://del.icio.us/tag/python

*Py: the Journal of the Python Language*
http://www.pyzine.com

Archive probing tricks of the trade:
http://groups.google.com/groups?oi=djq&as_ugroup=comp.lang.python&num=100
http://groups.google.com/groups?meta=site=groups&group=comp.lang.python.*

Previous - (U)se the (R)esource, (L)uke! - messages are listed here:
http://www.ddj.com/topic/python/ (requires subscription)
http://groups-beta.google.com/groups?q=python-url+group:comp.lang.python*&start=0&scoring=d&
http://purl.org/thecliff/python/url.html (dormant)
or
http://groups.google.com/groups?oi=djq&as_q=+Python-URL!&as_ugroup=comp.lang.python
There is *not* an RSS for "Python-URL!"--at least not yet. Arguments
for and against are occasionally entertained.


Suggestions/corrections for next week's posting are always welcome.
E-mail to <[email protected]> should get through.

To receive a new issue of this posting in e-mail each Monday morning
(approximately), ask <[email protected]> to subscribe. Mention
"Python-URL!".


-- The Python-URL! Team--

Dr. Dobb's Journal (http://www.ddj.com) is pleased to participate in and
sponsor the "Python-URL!" project.
 
C

Cameron Laird

http://groups.google.com/group/comp.lang.python/browse_thread/thread/ad0e15cb6b8f2c32/


#evaluate polynomial (coefs) at x using Horner's ruledef horner(coefs,x):
return reduce(lambda a1,a2: a1*x+a2,coefs)'Nuf said.Alan Isaac

No.

That is, this follow-up does *not* say enough for me to have confidence
of its intent. Leaving aside such formalities as the relation between
"Alan Isaac" and "David Isaac", I *think* you're supporting a claim
about the value of lambda with a specific example. Do I have that
right? Are you saying that your definition of horner() would suffer
greatly without lambda?
 
D

David Isaac

Jibes against the lambda-clingers lead eventually to serioushttp://groups.google.com/group/comp.lang.python/browse_thread/thread/ad0e15cb6b8f2c32/


Cameron Laird said:
I *think* you're supporting a claim
about the value of lambda with a specific example. Do I have that
right? Are you saying that your definition of horner() would suffer
greatly without lambda?

It is a simple example of how lambda and reduce can be very expressive.
Anyone who understands Horner's rule can see at a glance that this code
implements it. Anyone who has bothered to learn what lambda and reduce
do can see at a glance what the algorithm is.

It just cannot get simpler or more expressive.

Suffer greatly? Surely not. For "suffer greatly" you would probably need
to turn to people who do a lot of event-driven GUI programming.
But suffer, yes. Simplicity and expressiveness are valuable.
That is the point.

Cheers,
Alan Isaac
 
P

Peter Otten

It just cannot get simpler or more expressive.

But is it correct?
a0, a1, a2 = 1, 2, 3
x = 2
a0 + x*(a1 + x*(a2)) 17
def horner(coefs, x): return reduce(lambda a1, a2: a1*x + a2, coefs) ....
horner([a0, a1, a2], x)
11

Are we merely employing different conventions for the order of coefficients
or is that simple and expressive lambda/reduce stuff obscuring an error?

Peter
 
B

bonono

Peter said:
It just cannot get simpler or more expressive.

But is it correct?
a0, a1, a2 = 1, 2, 3
x = 2
a0 + x*(a1 + x*(a2)) 17
def horner(coefs, x): return reduce(lambda a1, a2: a1*x + a2, coefs) ...
horner([a0, a1, a2], x)
11

Are we merely employing different conventions for the order of coefficients
or is that simple and expressive lambda/reduce stuff obscuring an error?
I think horner needs the coefs be "reversed", comparing with how we
like to express polynomial in general, that is how I read those math
formulas about horner anyway.
 
C

Chris Mellon

http://groups.google.com/group/comp.lang.python/browse_thread/thread/ad0e15cb6b8f2c32/





It is a simple example of how lambda and reduce can be very expressive.
Anyone who understands Horner's rule can see at a glance that this code
implements it. Anyone who has bothered to learn what lambda and reduce
do can see at a glance what the algorithm is.

It just cannot get simpler or more expressive.

Suffer greatly? Surely not. For "suffer greatly" you would probably need
to turn to people who do a lot of event-driven GUI programming.
But suffer, yes. Simplicity and expressiveness are valuable.
That is the point.

As someone who does a tremendous amount of event-driven GUI
programming, I'd like to take a moment to speak out against people
using us as a testament to the virtues of lamda. Event handlers are
the most important part of event-driven code, and making them real
functions with real names is crucial to maintainable code. The only
reason to ever use a lamdba in Python is because you don't want to
give a function a name, and that is just not a compelling use case for
GUI events.
 
D

David Isaac

Peter Otten said:
But is it correct?
Yes.

Are we merely employing different conventions for the order of coefficients
or is that simple and expressive lambda/reduce stuff obscuring an error?

It is too simple and expressive to obscure an error. ;-)
This is particularly important since coefficient order is not standardized
across uses.

Cheers,
Alan Isaac
 
D

David Isaac

As someone who does a tremendous amount of event-driven GUI
programming, I'd like to take a moment to speak out against people
using us as a testament to the virtues of lamda. Event handlers are
the most important part of event-driven code, and making them real
functions with real names is crucial to maintainable code. The only
reason to ever use a lamdba in Python is because you don't want to
give a function a name, and that is just not a compelling use case for
GUI events.

Obviously opinions differ. See the discussion at
http://www.artima.com/forums/flat.jsp?forum=106&thread=98196&start=30&msRange=15
I find many of the pleas for lambda persuasive as well.
For the contribution of lambda to maintainability,
see e.g. Gary Robinson's comment at that link.

Alan Isaac
 
P

Paul Rubin

Chris Mellon said:
As someone who does a tremendous amount of event-driven GUI
programming, I'd like to take a moment to speak out against people
using us as a testament to the virtues of lamda. Event handlers are
the most important part of event-driven code, and making them real
functions with real names is crucial to maintainable code. The only
reason to ever use a lamdba in Python is because you don't want to
give a function a name, and that is just not a compelling use case for
GUI events.

I thought stuff like the following was idiomatic in GUI programming.
Do you really want separate names for all those callbacks?

# generate calculator keypad buttons
Button(label='7', command=lambda: user_pressed(7)).grid(column=1, row=1)
Button(label='8', command=lambda: user_pressed(8)).grid(column=2, row=1)
Button(label='9', command=lambda: user_pressed(9)).grid(column=3, row=1)

Button(label='4', command=lambda: user_pressed(4)).grid(column=1, row=2)
Button(label='5', command=lambda: user_pressed(5)).grid(column=2, row=2)
Button(label='6', command=lambda: user_pressed(6)).grid(column=3, row=2)
....
 
S

Steven Bethard

Paul said:
I thought stuff like the following was idiomatic in GUI programming.
Do you really want separate names for all those callbacks?

# generate calculator keypad buttons
Button(label='7', command=lambda: user_pressed(7)).grid(column=1, row=1)
Button(label='8', command=lambda: user_pressed(8)).grid(column=2, row=1)
Button(label='9', command=lambda: user_pressed(9)).grid(column=3, row=1)

Button(label='4', command=lambda: user_pressed(4)).grid(column=1, row=2)
Button(label='5', command=lambda: user_pressed(5)).grid(column=2, row=2)
Button(label='6', command=lambda: user_pressed(6)).grid(column=3, row=2)
...

While I don't spend much time on GUIs, code like that would scream
"refactor" to me, e.g. something like:

class UserPressedButton(Button):
def __init__(self, i):
def command():
return user_pressed(i)
Button.__init__(self, label=str(i), command=command)

Button(7).grid(column=1, row=1)
Button(8).grid(column=2, row=1)
Button(9).grid(column=3, row=1)

Button(4).grid(column=1, row=2)
Button(5).grid(column=2, row=2)
Button(6).grid(column=3, row=2)

STeVe
 
F

Fredrik Lundh

Steven said:
While I don't spend much time on GUIs, code like that would scream
"refactor" to me, e.g. something like:

class UserPressedButton(Button):
def __init__(self, i):
def command():
return user_pressed(i)
Button.__init__(self, label=str(i), command=command)

Button(7).grid(column=1, row=1)
Button(8).grid(column=2, row=1)
Button(9).grid(column=3, row=1)

Button(4).grid(column=1, row=2)
Button(5).grid(column=2, row=2)
Button(6).grid(column=3, row=2)

a temporary factory function should be sufficient:

def digit(label, x, y):
def callback():
# print "BUTTON PRESS", label # debug!
user_pressed(int(label))
Button(label=label, command=callback).grid(column=x, row=y)

# create numeric pad
digit("7", 1, 1); digit("8", 2, 1); digit("9", 3, 1)
digit("4", 1, 2); digit("5", 2, 2); digit("6", 3, 2)
digit("1", 1, 3); digit("2", 2, 3); digit("3", 3, 3)

are people still missing that local functions are inexpensive in Python ?

</F>
 
B

bonono

Steven said:
While I don't spend much time on GUIs, code like that would scream
"refactor" to me, e.g. something like:

class UserPressedButton(Button):
def __init__(self, i):
def command():
return user_pressed(i)
Button.__init__(self, label=str(i), command=command)

Button(7).grid(column=1, row=1)
Button(8).grid(column=2, row=1)
Button(9).grid(column=3, row=1)

Button(4).grid(column=1, row=2)
Button(5).grid(column=2, row=2)
Button(6).grid(column=3, row=2)
Well, that depends. This kind of coding many times are result of quick
copy and paste. Whether it worths to abstract things out really depends
on the life span. If it ends up never got touch again, the advntage of
lambda is that I can just have it as is, it works, is clear to
understand and everything is in place. I thought that is one of the
advantage of python or quick prototyping.

This also is not a very good example as it shows some form of
repetitiveness that is "screaming for refactoring". Many times, these
fields are similar but have no common functionalities.
 
P

Paul Rubin

Fredrik Lundh said:
a temporary factory function should be sufficient:

def digit(label, x, y):
def callback():
# print "BUTTON PRESS", label # debug!
user_pressed(int(label))
Button(label=label, command=callback).grid(column=x, row=y)

Looking at the calculator program I wrote a while back (one of my
first Python programs, written just to play with tkinter), I see that
I actually did something like that for the buttons. However, it also
contained (in the other order):

unops = {'sqrt': math.sqrt,
'sin': math.sin,
'cos': math.cos,
'tan': math.tan,
'ln': math.log,
'log': lambda x: math.log(x)/math.log(10),
'clr x': lambda x: 0
}

binops = {'+': (lambda x,y: x+y),
'-': (lambda x,y: x-y),
'*': (lambda x,y: x*y),
'/': (lambda x,y: x/y),
'**': (lambda x,y: x**y)
}

How would you refactor that, with no lambda?
 
P

Paul Rubin

Paul Rubin said:
binops = {'+': (lambda x,y: x+y),
'-': (lambda x,y: x-y),
'*': (lambda x,y: x*y),
'/': (lambda x,y: x/y),
'**': (lambda x,y: x**y)
}
How would you refactor that, with no lambda?

Ok, with operator.add and so forth. I don't remember if I knew about
those at the time. You can easily see though, how additional such
simple functions might be wanted, that aren't in the operator module.
 
B

bonono

Paul said:
Looking at the calculator program I wrote a while back (one of my
first Python programs, written just to play with tkinter), I see that
I actually did something like that for the buttons. However, it also
contained (in the other order):

unops = {'sqrt': math.sqrt,
'sin': math.sin,
'cos': math.cos,
'tan': math.tan,
'ln': math.log,
'log': lambda x: math.log(x)/math.log(10),
'clr x': lambda x: 0
}

binops = {'+': (lambda x,y: x+y),
'-': (lambda x,y: x-y),
'*': (lambda x,y: x*y),
'/': (lambda x,y: x/y),
'**': (lambda x,y: x**y)
}

How would you refactor that, with no lambda?

Or, why would you want to refactor that ? The lambdas were used as the
quickest and the most straight forward way to have the solution back
then I believe. Refactoring is an aftermath(performance, frequent
change to the same module for feature changes etc.).
Without lambda, even the first version would force the programmer to
think more about how to factor it and it seems in this case, not
necessary and waste of precious programmer time.
 
B

Bengt Richter

a temporary factory function should be sufficient:

def digit(label, x, y):
def callback():
# print "BUTTON PRESS", label # debug!
user_pressed(int(label))
Button(label=label, command=callback).grid(column=x, row=y)

# create numeric pad
digit("7", 1, 1); digit("8", 2, 1); digit("9", 3, 1)
digit("4", 1, 2); digit("5", 2, 2); digit("6", 3, 2)
digit("1", 1, 3); digit("2", 2, 3); digit("3", 3, 3)

are people still missing that local functions are inexpensive in Python ?

OTOH, (untested)

for label, x, y in ((str(d+1), d%3+1, 3-d//3) for d in xrange(9)):
Button(label=label, command=lambda d=int(label):user_pressed(d)).grid(column=x, row=y)

or

for tup in ((str(d+1), d%3+1,3-d//3) for d in xrange(9)): digit(*tup)

tweak 'til correct ;-)

Regards,
Bengt Richter
 
C

Christopher Subich

Chris said:
functions with real names is crucial to maintainable code. The only
reason to ever use a lamdba in Python is because you don't want to
give a function a name, and that is just not a compelling use case for
GUI events.

Ah, but that neglects the sheer utility of delayed-evaluation
expressions. Consider the key= parameter to list.sort, et. al:

complicated_list.sort(key=lambda x: x[3])

Decorate-sort-undecorate is another way of doing this, but it's also
boilerplate, involves list copies that have nothing to do with the flow
of the program itself, and can possibly error (if done naively: key is
comparable, but complex_list[0] isn't comparable, such as sorting a
list of complex numbers by the real part, if two or more items have the
same real).

The key= parameter was implemented just to make this sort of thing
clearer and easier (and, in an odd way, actually more semantically
explicit). The utility of a full function for the key= is nice and
necessary, but simultaneously a lot of the uses are going to be for
one-off expressions (like item[3]). There, the idea of a named function
seems conceptual overkill.

The most significant problem with Python's lambda is that it's billed as
an anonymous function, when it's really an encapsulated expression. My
preferred solution is to replace lambda with something along the lines
of an 'expression comprehension,' with similar syntax to list and
generator comprehensions as-is:

lambda param1, param2: stuff_with(param2,param1) would become

<(param1, param2): stuff_with(param2, param1)>
or, to become even more similar to comprehension syntax:
<stuff_with(param2, param1) with (param1, param2)>

The only real problem, parsing-wise, with this syntax is that it can
sometimes conflict with the << or >> operators if used without
whitespace near comparisons.

The scope of what can be contained in the expression comprehension
(lambda currently) is exactly the same as what can be contained in a
list/generator comprehension, so why not capitalize on the parallelism?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,073
Latest member
DarinCeden

Latest Threads

Top