Easy questions from a python beginner

Steven D'Aprano steve at REMOVE-THIS-cybersource.com.au
Thu Jul 22 23:45:22 EDT 2010


On Thu, 22 Jul 2010 18:34:11 -0400, wheres pythonmonks wrote:

> Okay -- so I promised that I would try the namespace mangling approach,
> and here's what I have come up with:
> 
> Approach #1:  Pass in the variables to be swapped as strings.  (boring)

Boring and slow and stupid. It makes an interesting trick to prove it can 
(almost) be done, but for production use? No way. There is nothing that 
*needs* call-by-reference that can't be done just as effectively using a 
slightly different approach.

This approach also has the fatal flaw that not all objects have names, or 
have only one name. In Python, objects are often anonymous, and the 
standard Python idiom for swapping works fine for them:

a = [1, 2, 3, "d", 5]
b = ["a", "b", "c", 4, "e"]
a[3], b[3] = b[3], a[3]

I expect your hack to choke and die if you try swapping anonymous objects.


[snip successful test of swapping using named globals]

As Carl already pointed out, this doesn't work outside of the global 
scope. 

This demonstrates an interesting lesson re testing. It's not enough to 
test these hacks with names in the global scope. You also need to test 
them with names in a local and nested scope, and in classes.


[...]
> Now, I want to make the above codes more "Pythonic"

The way to make them more Pythonic is to avoid them like the plague.

One of the differences in philosophy between Perl and Python is that 
Python doesn't approve of doing things just because you can. There is 
very little interest in or respect given to hacking Python. We're 
programmers, not hackers, and we look for the most simple way to do 
things, not the gnarliest or trickiest or least obvious way.

(Any yet, as a general rule, neither does Python particular get in your 
way. We have a saying: we're all adults here, if you want to shoot 
yourself in the foot, go right ahead.)

Occasionally, *very* occasionally, that makes it hard to do something 
that would be simple in another language. But much rarer than you might 
think, and a lot of popular programming idioms are work-arounds that are 
simply not needed in Python. E.g. call-by-reference itself was a work-
around to prevent unnecessary copying of large data structures like 
arrays in languages like Algol and Pascal (or so I understand). When Java 
guys come here and start asking how to implement design patterns in 
Python, 9 times out of 10 the answer is "you don't need it" rather than 
"you can't do it".

It's not quite true that we consider "hack" to be a pejorative, we're 
certainly true of the positive uses of the word. But as a general rule 
the Python community looks rather askance at anything that might be 
described as a hack. We're far more likely to describe something as a 
dirty hack than a cool, nifty or amazing hack.

It's not true, as some folks say, that there is "only one way to do it" 
in Python. But the Python ideal is for there to be "one obvious way to do 
it". If there's an obvious way, why would you look for an obscure, tricky 
hack? You better have a good reason for not using the obvious way, 
because writing the code is the *smallest* part of the job. You need to 
test it, and debug it, and maintain it, and they're all much, much harder.


> is there a way to:
> 
> 1.  Get the function's arguments from the perspective of the caller?

I don't understand the question.

If the caller passes arg = [1,2,3], then both the caller and the called 
function agree that the argument is the list [1,2,3]. Both caller and 
callee see the same list. It would be a pretty strange programming 
language where the called function saw something different from what the 
caller passed...



> 2.  Is there a better way to loopup by id?  I'm not very familiar with
> sys.exc_info, but creating the id->name hash each time seems like
> overkill.

No.


> 3.  Is there a reference on all the special variables, like __foo__?

If you're talking about "magic methods" and special attributes, like 
obj.__len__, then you should read this:

http://docs.python.org/reference/datamodel.html

This may also be helpful:

http://www.ironpythoninaction.com/magic-methods.html

If you're talking about special globals like __name__, I don't think 
there are any others. __name__ is (confusingly) documented here:

http://docs.python.org/library/__main__.html



> 4.  Is there any work on deparsing (like Perl's deparse) lambda
> functions to inline algebra and get a performance gain?

No. How would you do that? If I have something like this:


def my_func(arg):
    return some_class(1, 2, 3, callback=lambda x: arg.method(x))

how would you inline that? *Where* would you inline that?

Perhaps you're thinking that lambdas are commonly used like this:

def my_func(args):
    f = lambda a, b, c: 3*a + 4*b -2*c
    results = []
    for x in args:
        results.append(f(2, x, 3))
        results.append(f(x, x**2, x**3)
    return results

then, yes, that lambda could be inlined. But that's a rare and uncommon 
use for lambdas, and some would say unpythonic.

Even if you could inline it, CPython isn't big on micro-optimizations. 
It's generally considered that the extra complexity and risk of bugs 
isn't worth the tiny performance gain. Simplicity itself is a virtue, and 
many optimizations tend to be anything but simple, if not dirty hacks.



-- 
Steven



More information about the Python-list mailing list