Objects in Python

I

Ian Kelly

Those people are confused, then. Python is strongly typed: objects
always know their type, the type is always exact, and the type of an
object can't be changed.

Except when it can.
True

Cheers,
Ian
 
C

Chris Angelico

Yes of course I am, thank you for pointing that out.
I don't know why I have this overwhelming need to see variables explicitly
defined ... years of 'same old same old' I suppose.

Python's object model is not fundamentally incompatible with a system
of declared variables. I, too, like declaring my variables explicitly.
There are quite a few advantages to it:

1) Scoping is extremely clear. (Leaving aside anomalous behaviour like
Javascript's "var" declarations applying to a whole function.) You see
a declaration, you know that variable exists there and further inside
only. In a C-style language, that means it disappears at the
corresponding close brace.

2) Related to the above, you can infinitely nest scopes. There's
nothing wrong with having six variables called 'q'; you always use the
innermost one. Yes, this can hurt readability, especially taken to
this sort of stupid extreme, but that's a question for a style guide
and not a language design.

3) Variable-name typos can be caught at parse time. In Python, if you
misspell a variable, you've just made a new local variable.

It has its downsides, too, of course; mainly that it's (in some
people's opinion) syntactic salt. Why should I have to tell the
interpreter/compiler what it can figure out by itself? It's
duplicating information, and that's inefficient. It's like forcing all
your integer constants to be given in both decimal and hex, to catch
errors.

I'm of the opinion that the benefits are worth the effort. Others
disagree. It's hugely a matter of taste, and I'm just glad that there
are enough languages around that we can all have what we want :)

If you like the Python object model but want to add variable
declarations, grab me off list and I'll tell you about my personal
favorite language...

ChrisA
 
S

Steven D'Aprano

[...]
Looking at the self I'm assuming that's a method and not a function.


Actually, it is a function. It doesn't get turned into a method until you
try to use it.

The way methods work in Python is this:

Function objects are created by the "def" statement, regardless of
whether that is inside a class or not. So:

class X(object):
def spam(self, value):
pass

creates a single function object which takes one argument, self, and
sticks in in the class namespace X.__dict__['spam'] = spam

When you look up the name "spam" on an X instance:

x = X()
x.spam(42)

Python does it's usual attribute lookup stuff, finds the name "spam" in
the class namespace, and extracts the function object. So far that's just
ordinary attribute access. This is where it gets interesting...

Function objects are *descriptors*, which means that they have a __get__
method:

py> (lambda x: None).__get__
<method-wrapper '__get__' of function object at 0xb71bd77c>

Python sees that __get__ method and calls it with some appropriate
arguments (the class object and the instance object, I believe) and the
__get__ method constructs a method on the fly, handles the automatic bind-
instance-to-self magic, and returns the method object. And then finally
Python calls the method object with whatever arguments you provided.

As they say, "You can solve any problem in computer science with
sufficient layers of indirection". This descriptor protocol, as they call
it, is the mechanism behind methods, class methods, static methods,
properties, and probably other things as well.

You can do all sorts of funky things with descriptors -- google for
"descriptor protocol", "data descriptor", "non-data descriptor" etc. if
you are interested. Here's a trivial, but useful, one:

http://code.activestate.com/recipes/577030-dualmethod-descriptor/
 
S

Steven D'Aprano

2) Related to the above, you can infinitely nest scopes. There's nothing
wrong with having six variables called 'q'; you always use the innermost
one. Yes, this can hurt readability

Well, there you go. There *is* something wrong with having six variables
called 'q'.

Namespaces and scopes are work-arounds for the fact that, while there are
an infinite number of possible names, most of the good ones are already
taken.

Namespaces and scopes mean that I can use a name "q" even though I've
already used it for something else, but there is still cost to re-using
names (even if that cost is sometimes trivial).
 
S

Steven D'Aprano

Then maybe you should read more and write less.

I think that's uncalled for. Lipska isn't trolling. He's making
observations as he sees them. The fact that they're sometimes wrong is
not a reason to effectively tell him to STFU.

Better the misconception which is spoken allowed and corrected, then the
one which is kept quiet and festers.
 
S

Steven D'Aprano

We need to separate out the 'view' from the 'implementation' here. Most
developers I know, if looking at the code and without the possibly
dubious benefit of knowing that in Python 'everything is an object'
would not call this 'strong typing'

Most developers are wrong :)

A very useful resource to read is "What To Know Before Debating Type
Systems", which was put on the internet, lost, then found and put back up
here:

http://cdsmith.wordpress.com/2011/01/09/an-old-article-i-wrote/

I don't *quite* go so far as to agree that "strong typing" and "weak
typing" are meaningless, but they certainly don't mean quite as much as
people sometimes think.

It also includes this brilliant quote:

"I find it amusing when novice programmers believe their main job is
preventing programs from crashing. ... More experienced programmers
realize that correct code is great, code that crashes could use
improvement, but incorrect code that doesn’t crash is a horrible
nightmare."

In Python's case, we say:

1) objects are strongly typed -- every object has a type, which is
usually immutable and sometimes known at compile time;

2) names (what some people insist on calling variables) are not typed at
all (with the exception of a handful of keywords like None);

3) most Python built-ins are strongly typed, and users are discouraged
from writing excessively weakly-typed operations (you could write an int
subclass that can be added to a string or a list, just as you can add it
to a float, but you shouldn't);

4) there's a culture of preferring "duck typing", which is kind of an ad
hoc form of interfaces, over strict type testing, so users are also
discouraged from writing excessively strongly-typed operations (if you
just need something you can iterate over, why insist that it must be a
list and nothing but a list?).
 
E

Evan Driscoll

You haven't discovered anything about types; what you have discovered is
that Python name bindings are not variables.

In fact, Python doesn't have variables – not as C or Java programmers
would understand the term. What it has instead are references to objects
(with names as one kind of reference).

OK, I've seen this said a few times, and I have to ask: what do you mean
by this? I consider myself pretty decent at Python and other languages,
and I really don't get it.

Especially the comparison to Java variables. Java programmers are quite
used to variables which are references to objects: everything that's not
a primitive type is a reference, and it's kinda hard to determine
whether primitives are references or actual primitives.

And many other languages have reference behavior and still call their
bindings "variables", e.g. Scheme.

Evan



-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (MingW32)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iQEcBAEBAgAGBQJQNbZUAAoJEAOzoR8eZTzgsz0H/jGpiNIeoxoehUJRwztrfLi/
4MK018vzzUf5bzuo7WnB4lCvtMf+oOcaDuwarg8N+3oIJ8YCLHhSVSI+vwWp5I8b
fLrw+ld1FD3xIETsDxcll3+aRkwIXL53kvEQC3qwHGWeENHc/bMhePJz2PQopGgt
m9qXmrYKeP9gScrqGgfFJLrlbJ5LYDRu0iLQJNXbB1cWuYfbzI3GQyfsX9sxs24n
4YNI8p1RpZUnjDAgFoCTMW9a/3mydjbE4T3FJAba/hpyAxobwtCed2WRaLdxzYKN
NZCKBnnSNKwQxYoamyt38wuiWGpaV0Kw33ED/l2AjqfJCR8ZyiywDMb3UqsuPfA=
=VDkg
-----END PGP SIGNATURE-----
 
C

Chris Angelico

OK, I've seen this said a few times, and I have to ask: what do you mean
by this? I consider myself pretty decent at Python and other languages,
and I really don't get it.

Simple example that'll work in many languages:

x = 1;

In C, this means: Assign the integer 1 to the variable x (possibly
with implicit type casting, eg to floating point).

In Java or C++, this means: Assign the integer 1 to the variable x.
Ditto, but possibly 'x' is actually a class member etc rather than a
simple variable.

In Python, this means: Make the name x now refer to the object 1.
Whatever x had before is de-referenced by one (in a simple refcounting
situation, that may result in the object being destroyed), and the
object referred to by the literal 1 is now pointed to by x.

Names are just one kind of reference because complex objects can have
unnamed references. For instance:

foo = [1, 2, 3]
foo[1] = "Hello, world!"

The second element of foo just got rebound in exactly the same way x
did, but it doesn't have a name of its own.

Does that sort things out, or just make things more confusing?

ChrisA
 
S

Steven D'Aprano

OK, I've seen this said a few times, and I have to ask: what do you mean
by this? I consider myself pretty decent at Python and other languages,
and I really don't get it.

I think the point that Ben would like to make is that while "name
binding" is a specific kind of "variable", the word "variable" comes with
too much baggage from the old-school C, Pascal etc. style of variables-
are-named-memory-locations. Most of the time, the differences are
unimportant, but when they are important, if your mental image is that
Python "variables" (name bindings) are like C or Pascal
"variables" (memory locations), you're going to get confused.


[...]
And many other languages have reference behavior and still call their
bindings "variables", e.g. Scheme.

Yes, well in my opinion, a great deal of the terminology in use is
absolutely dire. E.g. both Ruby and Java have the exact same parameter
binding strategy as Python, only the Ruby people call theirs "call by
reference" and the Java people call theirs "call by value", *both of
which are identical*, and NEITHER of which are the same thing that C and
Pascal programmers will understand by call by value *or* call by
reference.

http://mail.python.org/pipermail/tutor/2010-December/080505.html
 
J

Jussi Piitulainen

Steven said:
I think the point that Ben would like to make is that while "name
binding" is a specific kind of "variable", the word "variable" comes
with too much baggage from the old-school C, Pascal etc. style of
variables- are-named-memory-locations. Most of the time, the
differences are unimportant, but when they are important, if your
mental image is that Python "variables" (name bindings) are like C
or Pascal "variables" (memory locations), you're going to get
confused.

I don't get it either. To me the python-has-no-variables campaigners
seem confused. As far as I can see, Python can be seen in terms of
variables bound to (locations containing) values perfectly well, in a
way that should be quite familiar to people who come from Java (or
Lisp, Scheme like me).

It is very bad that people campaign here against the terminology that
is used in the official Python language reference and the Python
tutorial.

Best would be to simply explain how the variables, values, assignment,
and calls work in Python, the way the language reference and tutorial
actually do.

If the no-variables campaign is to continue, the language reference
and the tutorial should be changed to match. I would consider it a mad
move, but the current practice of badmouthing the official wording is
not healthy either.
[...]
And many other languages have reference behavior and still call
their bindings "variables", e.g. Scheme.

Yes, well in my opinion, a great deal of the terminology in use is
absolutely dire. E.g. both Ruby and Java have the exact same
parameter binding strategy as Python, only the Ruby people call
theirs "call by reference" and the Java people call theirs "call by
value", *both of which are identical*, and NEITHER of which are the
same thing that C and Pascal programmers will understand by call by
value *or* call by reference.

That's indeed such a mess that those call-by-* terms may be now best
avoided. I would also avoid any distinction between an object and a
"reference" to an object, except as an implementation detail. It's not
helpful. It only leads to the confusion where it seems that Java (or
Python) does not actually have objects at all, only references to
objects, which in turn don't exist, so, er, what.

The swap function is helpful. Why doesn't it work? Because it assigns
to different variables that are local to the function. If I pass it a
list, why can it then swap the elements? Because that is the same
list, not a copy. Get used to it. Works for me.
 
M

MRAB

I don't get it either. To me the python-has-no-variables campaigners
seem confused. As far as I can see, Python can be seen in terms of
variables bound to (locations containing) values perfectly well, in a
way that should be quite familiar to people who come from Java (or
Lisp, Scheme like me).
[snip]
In Java a variable exists even when it has not been assigned a value.
In Python, on the other hand, the basic model is that a 'variable'
doesn't exist until it has been bound to an value (although, for
efficiency reasons, that's not entirely true, because at compile time
CPython will identify the local variables in a function and allocate a
'slot' for it).
 
J

Jerry Hill

I don't get it either. To me the python-has-no-variables campaigners
seem confused. As far as I can see, Python can be seen in terms of
variables bound to (locations containing) values perfectly well, in a
way that should be quite familiar to people who come from Java (or
Lisp, Scheme like me).

Personally, when I was learning python I found the idea of python
having names and values (rather than variables and references) to
clear up a lot of my misconceptions of the python object model. I
think it's done the same for other people too, especially those who
come from the C world, where a variable is a named and typed location
in memory.

Perhaps those that come from the Java and Lisp world don't find the
name/value paradigm as helpful. Still, it seems silly to excoriate
people on the list for trying to explain python fundamentals in
several different ways. Sometimes explaining the same idea in
different words helps people understand the concept better.
 
E

Evan Driscoll

Well we don't want to turn this into a language comparison thread do we,
that might upset too many people but I can't remember ever writing a
method that took an Object as argument, you just can't do that much with
an Object.

In the pre-Java-1.5 days, functions that took Objects were *very*
common; e.g. every collections class. Even now there are probably
lingering cases where either there's some code that hasn't been
genericized or is too much work to genericize to make it worthwhile. (I
do very little Java programming so can't point to any concrete cases if
you would (reasonably) reject the example of java.util.collections being
used in their non-generic form.)

Anyway, the point wasn't that 'foo(Object o)' is common, just that
you've probably seen something which is somewhat comparable.

Evan



-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.5 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iQEVAwUBUDZd0gOzoR8eZTzgAQLz3Qf9F93tHIkqSgMt4wEcvMBttLE//kngTfLK
8HrxVGwGbLYzqXZN+315a7ZaNpBUZGbu2On2Y/dsfRAIPhExrSmVTrQWrIqErG1S
72doRFDFzcfh6EHD/dvvQ+1DKRJ9iqnDRwGnr1xtyOjLbILMAXx8PDCkTA25VXCm
+gYn+RiPfWfWlyAHmXTEtnijtJbryNrFyniUjuHMdUw5AcABj/IGp1+NE+0o7E0j
AUC0zxzm6vR5Ssy7o3e3wPc5Ie1PTYtjrIX5OLM4OCz43/GoXlgklFOePMIYT76o
mMSyqUb7wmvdZ3DUkozK8lt50MG/RWvaX+3lKfxxO1GjJ/WN8ShTSQ==
=DuQ0
-----END PGP SIGNATURE-----
 
R

rusi

Most developers are wrong :)

A very useful resource to read is "What To Know Before Debating Type
Systems", which was put on the internet, lost, then found and put back up
here:

http://cdsmith.wordpress.com/2011/01/09/an-old-article-i-wrote/

Thanks for that article.
There was one by Peter Wegner -- exact one I cant find. Here's a good
approximation:
http://analysis-of-persistence-tools.googlecode.com/files/p7-wegner.pdf

Section 5.2.1 in particular has 7 different things that the word
'type' could mean to different types(!) of programmers.
 
E

Evan Driscoll

[I have some things to say to a few people so I'm just putting it all in
one rather than clutter up your email box even more.]

[Snip discussion on names vs variables]

Does that sort things out, or just make things more confusing?

ChrisA

I... am not sure. I don't think it really told me anything new. I think
it's just that I don't think that any of the distinctions (nor all of
them put together) makes it worthwhile to reject a perfectly good term
in common use just because the behavior of Python variables is a bit
different from the behavior of variables in *some* other languages.

For instance, I don't get annoyed that both Java and Python use the
terms "class" and "object" for similar but still very different things.
And while I think it's worth saying "Python classes and objects are
rather different from Java's", I definitely *wouldn't* say "Python
classes aren't really classes" -- even though (I assert) Python classes
are *far* further from Simula-style (/Java/C++) classes than Python
variables are from Java variables.


I would also avoid any distinction between an object and a
"reference" to an object, except as an implementation detail. It's not
helpful.

Whaaaa....?

How would you describe it then? To me, that distinction is absolutely
*fundamental* to understanding how languages like Python/Scheme/Java
work, because it tells you how to reason about aliasing behavior in an
unconvoluted way (which is essential to understanding how they work).

How would *you* suggest dealing with that issue?


...

Perhaps those that come from the Java and Lisp world don't find the
name/value paradigm as helpful. Still, it seems silly to excoriate
people on the list for trying to explain python fundamentals in
several different ways. Sometimes explaining the same idea in
different words helps people understand the concept better.

I agree with this, and I'm happy that people found it useful.

*However*, this thread wasn't really prompted by someone just trying to
explain variables in different terms -- it was prompted by one of the
many comments you see from time-to-time that "Python doesn't have
variables – not as C or Java programmers would understand the term".
That's a different than saying "here's another way of looking at Python
variables", and that instance is even toned down compared to a lot of
the instances you'll find (which will often omit the qualification at
the end).

To me, saying "here's an alternative way to look at variables" is great,
but saying "Python doesn't have variables" is, IMO, at least as silly as
what Jussi said. To me, dancing around the issue just leads to more
confusing terminology and makes things worse.

(And this is reinforced by the fact that neither I nor Google seems to
have really seen "Python doesn't have classes" ever used, when that
statement is at least as true as "Python doesn't have variables".)

Evan


-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.5 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iQEVAwUBUDZljwOzoR8eZTzgAQJ9tAf9GLEfEG04Ficl1bhJtdYrIQRsQYMTlb5E
y2e/sSa7FIC4hUG0Zz8j3jfVRu0sWLZ7+K3VYZvE5tkXSOMugeT1VQdZH4Wl7hcZ
b/bx/xr89ksZsxpRiLD5HGVSMGIqsPyiwqR/zlkKFmZi9yXcTa1udPkIhrZv+FmU
4mYhakEawC0V2i3UIEJGzt9dNXeak0QdR9eckSw88TpEfP7M8hSG/wnlkVoifT8w
1qCcp0bcte73XQXQ5czlsTJG2BOmtVMfVZ57X9AmFBHu5x4Qoc0oEsHaZTxW8VYw
fzEGDpgce1BxRWnwiEzh5LIGQPAhkT47pFUsZA/Ng3QxPnkV/eUyOg==
=DrXD
-----END PGP SIGNATURE-----
 
T

Terry Reedy

Personally, when I was learning python I found the idea of python
having names and values (rather than variables and references) to
clear up a lot of my misconceptions of the python object model. I
think it's done the same for other people too, especially those who
come from the C world, where a variable is a named and typed location
in memory.

There are two important points about C and assembler. First, the named
locations (and un-named internal locations like function return
addresses) are *contiguous*. Giving a user access to one block may give
a user access to other blocks if one is not careful. The other is that
the typing is in the code and compiler, but not in the runtime memory.
So text input can be read as code and a return jump address to the bytes
interpreted as code.
 
S

Steven D'Aprano

I definitely *wouldn't* say "Python
classes aren't really classes" -- even though (I assert) Python classes
are *far* further from Simula-style (/Java/C++) classes than Python
variables are from Java variables.

Well, Python classes are first-class (pun not intended) objects in their
own right, and hence are data. Java and C++ classes are not, they are
instructions to the compiler rather than data.

But other than that, what do you see as the difference between Python
classes and Simula-style classes?


Whaaaa....?

How would you describe it then? To me, that distinction is absolutely
*fundamental* to understanding how languages like Python/Scheme/Java
work, because it tells you how to reason about aliasing behavior in an
unconvoluted way (which is essential to understanding how they work).

How would *you* suggest dealing with that issue?

Given:

x = some_object()
y = x

I could say that x and y are the same object, rather than x and y are
references to the same object.

Sometimes, when I say "x", I mean the *name* x, which is a reference to
some object.

Much more often though, when I say "x", I use it as a convenient label
for some object. Rather than saying "the object which is referenced to by
the name x", I just say "x".

Nearly always, the meaning is obvious in context.


[...]
*However*, this thread wasn't really prompted by someone just trying to
explain variables in different terms -- it was prompted by one of the
many comments you see from time-to-time that "Python doesn't have
variables – not as C or Java programmers would understand the term".

No offence to Ben Finney, but I think sometimes he's a bit too eager to
emphasise the subtle differences between Python and other languages,
rather than the similarities. (I used to be like Ben in this regard, but
I got better -- or worse, depending on your perspective.)

Again, context is important: sometimes I will choose to gloss over the
differences by calling x a variable, and sometimes I will emphasise the
differences to C or Pascal by referring to name binding.

To me, saying "here's an alternative way to look at variables" is great,
but saying "Python doesn't have variables" is, IMO, at least as silly as
what Jussi said. To me, dancing around the issue just leads to more
confusing terminology and makes things worse.

(And this is reinforced by the fact that neither I nor Google seems to
have really seen "Python doesn't have classes" ever used, when that
statement is at least as true as "Python doesn't have variables".)

I think you are utterly wrong here.

Python has classes. They are created by the "class" keyword. Whether
those classes are identical to Java classes is irrelevant -- in Python,
these whatever-they-are-things are called "classes", and so Python has
classes.

But Python does not have things called "variables". There is no
"variable" keyword to create a variable. It is absolutely fundamental to
the programming model of Python that it has objects which are bound to
names in namespaces (and other entities, such as list items). That is
*critical* -- Python uses name bindings.

But name bindings are a kind of variable. Named memory locations are a
*different* kind of variable. The behaviour of C variables and Python
variables do not follow the Liskov Substitution Principle -- you can't
rip out the entire "names bound to objects" machinery of Python and
replace it with C-like named memory locations without changing the high-
level behaviour of Python. And so by some ways of thinking it is *wrong*
to treat name bindings and memory locations as "the same sort of entity".
Hence, if C variables are variables, then Python name bindings can't be.

I used to agree with that reasoning. I no longer do, not entirely. While
I see the differences between them -- for instance, C variables exist
before they have a value assigned to them, Python name bindings do not --
I don't think the differences are important enough to *prohibit* use of
the word "variable" to describe name bindings. Only to discourage it.
 
J

Jan Kuiken

Well, there you go. There *is* something wrong with having six variables
called 'q'.

Sometimes you don't want only six variables called 'q' but a hundred
of them :)

def fac(q):
if q < 1 :
return 1
else:
return q * fac(q-1)

print(fac(100))


Jan Kuiken
 
I

Ian Kelly

Sometimes you don't want only six variables called 'q' but a hundred
of them :)

def fac(q):
if q < 1 :
return 1
else:
return q * fac(q-1)

print(fac(100))

That's only one variable called 'q', instantiated 100 times simultaneously.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,777
Messages
2,569,604
Members
45,202
Latest member
MikoOslo

Latest Threads

Top