Newbie look at Python and OO

Bruno Desthuilliers bdesth.quelquechose at free.quelquepart.fr
Thu May 10 17:12:50 EDT 2007


walterbyrd a écrit :
> I learned to program with Pascal, way back when. Went into software
> development for a while, then went into systems admin. Have programmed
> in several languages, just learning Python.
> 
> Some things I find odd:
> 
> 1) 5/-2 == -3?

integer division.

> 2) list assignment handling, pointing two vars to the same list:
> 
> With simple data types:
> 
>>>>a = 5
>>>>b = a
>>>>a = 3
>>>>a,b
> 
> (3, 5)
> 
> Which is what I'd expect, since I have changed a, but not b.

s/changed/rebound/

> But with lists:
> 
>>>>a = list("1234")
>>>>b = a
>>>>a.append("5")
>>>>a,b
> 
> (['1', '2', '3', '4', '5'], ['1', '2', '3', '4', '5'])
> 
> b  changes even though I have not touched b.

You did call a mutating method on the object pointed by both a and b. 
You're comparing apples and oranges here. The second snippet should be:

 >>> a = [1, 2, 3]
 >>> b = a
 >>> a = [4, 5, 6]
 >>> a, b
([4, 5, 6], [1, 2, 3])
 >>>

> I know why, but this is
> not what I would ordinarilly expect, it does not seem intuitive.

If so your intuition is based on misconceptions. In Python, a 'variable' 
is really a name=>object_ref pair in a namespace (think of namespaces as 
  dicts). The name by itself is only that : a name. The "value" is 
*always* a reference to an object, and a same object can be referred to 
by many names. In Pascal terms, this is similar to (smart) pointers to 
records.

> And,
> IMO, it gets worse:
> 
> 
>>>>a = list("1234")
>>>>b = a
>>>>a = a + ['5']

Here you're rebinding the name 'a' to a new list object which is the 
concatenation of the list object previously bound to 'a' and the 
(anonymous) ['5'] list object.

>>>>a,b
> 
> (['1', '2', '3', '4', '5'], ['1', '2', '3', '4'])


> Sometimes changing a changes b, and sometimes not.

Rebinding a name doesn't affect the object previously bound to it. 
Changing the state of an object of course affects the object.

> You also have to
> remember that subseqent changes to a will not change b - after some
> operation but not others.

Binding and method calls are quite distinct operations.

> To those who think in Python, I'm sure this
> all seems normal. But, having programmed in about one dozen other
> language, this seems downright bizare to me. I know why it works like
> this, but it seems like an odd way to do things.

This is obvious when stop thinking in term of "boxes" (ie: a variable is 
a box containing a value) and start thinking in terms of references.

> 3) ambiguous use of the form: this.that()
> 
> Sometimes, this.that() means module.funcion() as in: 
> 
>>>>os.dirlist(".")
> 
> 
> Other times, "this" is sort of like a parameter to the "that"
> function:
> 
> 
>>>>a = list("1234")
>>>>"_".join(a)
> 
> '1_2_3_4_5'
> 
> And still other times, is seems that "this" is an object, acted upon
> by "that" :
> 
> 
>>>>a = list("1234")
>>>>b = "_".join(a)
>>>>b.split("_")
> 
> ['1', '2', '3', '4', '5']

In *all* cases, 'this' is an object, and 'that' is an attribute of 
'this'. This is definitively not ambiguous. You have to understand that 
everything in Python is an object - including functions, classes and 
modules.

os.listdir : this is the (function object) attribute 'listdir' of module 
object os
 >>> hasattr(os, 'listdir')
True
 >>> listdir = getattr(os, 'listdir')
 >>> listdir.__class__
<type 'builtin_function_or_method'>
 >>>

"_".join : this is the (method object) attribute 'join' of class str:
 >>> ''.__class__
<type 'str'>
 >>> hasattr('', 'join')
True
 >>> join = getattr('', 'join')
 >>> join.__class__
<type 'builtin_function_or_method'>
 >>>

b.split: this is the (method object) attribute 'split' of class str.

In these three examples, these attributes are callable objects, and you 
apply the call operator to them.

> BTW: it seems a bit odd to that the positions of the string, and the
> delimitor, are reversed between the complementory functions join(),
> and split().

Yes, it's a bit surprising at first. But it's still logical.
   some_string.split(delimiter) => new_list
   delimiter.join(some_list) => new_string

> I suppose if it weren't for OO, we have something
> terribly complicated, like:
> 
> split(str, "_")
> join(str, "_")

This should be:
   join(list, "_")

> Again, those who think in Python, will understand right away that:
> 
> math.count(x)
> 
> is counting the substring "x" in the "math" string. But can you see
> where that might be confused to be a function called count() in the
> math module?

No, I can't. Because
1/ my functions (or methods) are too short for such a confusion to be 
possible
2/ I wouldn't name a string "math"

> I'm not complaining. Python is a great language in many respects. But,
> I would take some issue with those claiming Python is intuitive and
> easy. IMO: there seems to be many ambiguous, unintuitve, and
> confusing, aspects to Python.
> 
I guess this has to do with your (very procedural) background. Of 
course, Python does have it's share of gotchas and warts, but it's one 
of the only languages I know that you can start to be productive with in 
a matter of days.



More information about the Python-list mailing list