A bundle of questions from a Python newbie

Gonçalo Rodrigues op73418 at mail.telepac.pt
Wed Feb 20 16:58:50 EST 2002


Hi all,

A few months ago I started groking at Python. I am not a computer
scientist or a professional programmer and in my activity (mathematics)
I hardly do any programming at all - and if I needed to I would almost
surely use something like Mathematica.

Still, I do some programming in my spare time and besides, since my
early teens I have been fascinated with computer programming. Along the
way I have "learned" several languages like BASIC, C, Java and Ruby, but
never actually got around doing anything useful with them, because of
lack of time, patience and self-discipline, and also because the
languages themselves never helped, forcing me to pay attention to
nitty-gritty boring details. And then came Python. The clean and
uncluttered syntax is just amazing. I actually have fun programming with
Python and that is why in these few months I've already done some COM
programming and dished out some GUI's via wxPython, assembling these in
a program that actually accomplishes something useful. This makes me
believe that Python is very benign and gentle towards newbies like me.
So much so that I am thinking in tackling some more serious projects.

But enough babbling. I have several questions on the rationale of
Python. I don't know if this is the best option, or if I'm breaking some
netiquette rule, but I've decided to bundle them in a single post. My
aim in making these questions is to understand what lies behind the
specific choices that were made in designing Python, to get myself
acquainted with the Pythonic mind-set so to speak.

Here they go:

1. The way I thought that an assignment like

var += 1 

worked was that the interpreter would go to the place pointed by var and
add 1. In particular, id(var) should remain constant. But this is not
what happens as a simple test shows it. So what is wrong in my
perception of what += does? Is this an implemetation issue?

2. What is the idea of having in the loop

for var in range(10):
    pass

the var variable still available after it? Wasn't it supposed to die (as
in being out of scope) when the loop ends? And is this a feature, or
something that we should not count on? Somehow, I believe that the a new
var should be created when the loop starts and then destroyed when it
ends avoiding any variable shadowing along the way.

3. This is not a question just a small complaint. I really miss the
do-until control flow in Python. I always have to waste some extra brain
cycles to convert it to the while 1, etc. idiom. Hey, we all have a
right to our complaints, right? ;-)

4. I have read the FAQ about the "self controversy" - why one has to
declare it as an argument and then use it explicitly in the body of the
method - but I really feel that there must be a better solution. I
thought something like this could be useful:

a. self doesn't need to be declared.

b. Distinguishing data members from local variables could be achieved by
instead of using self.whatever use .whatever - a single dot in front of
the name "whatever".

I don't expect that this solution is adopted (it would break all the
existing code - ahhh every Nero-like language designer's dream - wreak
havoc in the citadel of its users and start afresh), what I would like
to know is how bad/good is this idea.

5. The FAQ explains why adding methods to built-ins is disallowed (btw,
IMHO I find this to be one of the few strong points of Ruby when
compared to Python).

Still, What's the rationale behind allowing

class L(list):
    pass

L.answer = 42

but then not allowing 

L.__dict__['answer'] = 42

6. Is there a reason why 3.__abs__() does not work? After all 3 is an
object (in the wider sense of the word). And it does work if we assign
it to a variable, eg, 

var = 3
var.__abs__()

I know that code like the above (methods applied to number literals) is
probably rare, but consistence is also a good thing.

7. What is the reason why (new-style) classes do not allow assignment to
__bases__?

8. Can the id() of an object change? e.g. via the garbage collector
moving it around? I'm asking this, because in the negative case, mutable
user-defined classes could be made hashable by adding an attribute with
the id() of the object and then defining __hash__ to return this
integer.

P.S: I'm well aware that hashing in a dictionary relies on comparison by
value and the above would be by identity. A single consistent choice is
the best and I have no qualms on the by-value choice, still the
by-identity is sometimes useful.

9. What would be better in terms of speed?

for i in range(<whatever>):
    <whatever> 

Or to code an iterator like

from __future__ import generators

class Range:
    def __init__(self, end, start = 0, step = 1):
        self.end = end
        self.start = start
        self.step = step

    def __iter__(self):
        i = self.start
        while i < self.end:
            yield i
            i += self.step

and then use it in the for loop.

10. I have a class that works like a list in the sense that supports the
method __getitem__ and its relatives. But I'm at a loss as to what I
have to do to support the slice notation.

11. Generators seem to be a very powerful concept. Still,

a. Why can't a return statement have an expression?

b. Is there any way to "reset" a generator, e.g. upon a subsequent call
it starts as if it is being called for the first time?

12. This is not exactly about Python, but about programming in general.
I keep reading about continuations and coroutines and I would like to
know, in simple terms if possible, what the heck are they and in what
ways they differ from generators as they exist in Python.

My deepest-deepest thanks for any comments/answers.

With my best regards,
Gonçalo Rodrigues.




More information about the Python-list mailing list