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