On Thu, 07 Oct 2010 20:10:14 -0300, Rogério Brito wrote:
> What is the Pythonic way of writing code like this? So far, I have > found many alternatives and I would like to write code that others in > the Python community would find natural to read. Some of the things > that crossed my mind: > > v = [0 for i in range(20)] Absolutely not. Such a code snippet is very common, in fact I've done it myself, but it is a "hammer solution" -- to a small boy with a hammer, everything looks like a nail that needs hammering. Writing such a list comprehension is a "list comp solution". > v = [0] * 20 Yes, this is the solution. But given your earlier explanation that you want to lazily initialise v, I don't think it applies, because it initialises it all at once. (Of course, such initialisation is cheap, but it does happen all at once.) If you are writing this: v = [] # declare v as an empty list do_something() do_something_else() v = [0]*20 # now initialise v before using it do_something_with(v) then such declarations are not necessary and are discouraged in Python. Having an unused, empty variable v floating around doing nothing is pointless in Python. Just write: do_something() do_something_else() v = [0]*20 # create v before using it do_something_with(v) > v = [] > for i in range(20): v.append(0) I would never write that literally. It's as bad as the list comp, only it takes up more space. It too also fails to be lazy initialisation. However, using append is the correct way when you have a situation where you need to dynamically grow the list, e.g.: v = [] for i in range(20): v.append(0) do_something_with(v) Two more alternatives: v = list(range(20)) # in Python 2.x you can leave out the call to list() or v = [] v.extend(range(20)) both initialise v to [0, 1, 2, 3, ... , 19] instead of [0, 0, ..., 0]. > 2 - If I declare a class with some member variables, is is strictly > necessary for me to qualify those members in a method in that class? For > instance, if I define: In Python, we generally refer to "attributes" rather than "members". > class C: > f = 1 > def g(self): > return f By the way, you have created a class attribute f which is shared by all instances. You probably want: class C: def __init__(self): self.f = 1 def g(self): return self.f > I get an annoying message when I try to call the g method in an object > of type C, telling me that there's no global symbol called f. No you don't. You get a message that there is no global NAME called f. You might think I'm being pedantic, but I'm not. If you're thinking in terms of C language, you probably think that there is a symbol table created by the compiler so that Python can look at a reference "f" and say "oh, that's a member variable" at compile time, and only the correct value needs to be looked up at runtime. But that's not Python's execution model. *Everything* in Python is looked up dynamically at runtime in namespaces. (The only exceptions are statements.) So when you write "f", Python *cannot* know at compile time whether it is a local variable, a non-local, a global, an attribute (member) or something else. It must look the name up in one or more namespaces at runtime. (Of course, you might already know this, in which case, yes, I'm just being pedantic *grins* ) > If I make > g return self.f instead, things work as expected, but the code loses > some readability. On the contrary, it increases readability, because it explicitly tells the reader that you are accessing an attribute f rather than a local variable. Remember that Python uses nested namespaces. Inside the method C.g above the namespaces that are searched are: local variables any non-local (nested) functions or closures (none in this example) global variables built-ins in that order. Each namespace is independent, and Python will never try to guess that f is an attribute of the instance or class unless you explicitly tell it so. For example, an attribute instance.len will never block access to the built-in function len(). (Actually, there is one exception... when a class statement is executed for the first time, creating the class, local variables of the class block are identified as attributes. This is a case of practicality beats purity, since otherwise Python would need extra syntax for creating methods and class attributes.) Attributes have their own search order: instance attributes class attributes attributes of any base classes When you refer to instance.attribute, the namespaces are searched in that order for the name "attribute". The locals and globals are not searched. Hope this helps, -- Steven -- http://mail.python.org/mailman/listinfo/python-list