Objects in Python

D

Dennis Lee Bieber

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).
Or, at an even lower level...

Convert the decimal literal "1" to binary (including type casting)
to the predeclared type given to the variable "x", and store that binary
value into the predetermined memory associated with "x".

Both the type, and the memory location, are fixed to the name "x"
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.
The type, and memory location, are inherent attributes of the
integer object; "x" is just a name by which the object may be accessed.
 
E

Evan Driscoll

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?

So first, to some extent that's like saying "these two different things
are different in this important way, but other than that, what's the
difference?" :)

But there are some other differences. (Not all of these are strictly
with classes per se, but I would say they all have strong interactions
with the object system.)

* Explicit 'self'. OK, this sounds just like a minor syntactic
difference, and in some respect it is. (For some time I considered it
an annoying piece of syntactic salt.) But it has significant
interactions with other things which you can do, such as using a
method as just a normal function ('type(c).f(c)' ~= 'c.f()')
or attaching other functions to an instance or a class (more on that
later).

This is definitely my weakest argument. :)

* Fields. In Simula-style classes, you can tell easily what fields a
class and its objects contain. In Python, that question from some
point of view doesn't even make sense (in the absence of __slots__).
Fields are a property of the *objects* rather than the class, and
two objects of the same class don't necessarily have the same fields.

Related to this point we have...

* What it means for an object to have a particular class type. With
Simula-style classes, if I have an object 'o' of class 'c', then I
know that 'o' has the functions and fields defined by 'c'. Now, the
virtual functions may have been overriden in base classes and stuff,
and maydbe they'll always fail, but I at least know they're *there*.

In Python, I know... well, nothing basically. As far as I know, it's
possible to make it so that o's only relation to 'c' is what
'type(o)' and 'instanceof' say. (And maybe you can even override
those, I dunno!) You can go through and add/remove/replace functions.
Two different objects of the same class may have completely disjoint
sets of attributes.


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.

Huh, fair enough.

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.

OK, let's make a new language. I'll call it 'Python--' because at least
*I* wouldn't want to program in it. :)

In Python--, any time you use a name, you have to prefix it with the
word 'variable':
variable x = 4
print(variable x)

Does Python-- have variables? Does Python? To me, the answer to those
questions basically has to be the same -- after all, the new 'variable'
keyword didn't really change the language, just have it a slightly
different concrete syntax. Heck, if I wanted to implement Python--, the
only thing I'd have to change in a Python implementation is the lexer!

And if you say "no, Python-- doesn't have variables, it just has
something that it wrongly calls variables", then it's no contradiction
to say "Python doesn't have classes, it just has something that it
wrongly calls classes."

Think of it as duck-typing the term "variable". :) To me, Python locals
and globals look and quack like a variable.



Incidentally, I also realized another reason I don't like the 'names'
description. Take 'foo.bar'. (That is, the 'bar' attribute in object
'foo'.) Is 'foo.bar' a name? I'm not sure what the 'names' proponents
would say, but to me both answers are problematic. I *really* dislike a
'no' answer because to me, 'foo.bar' absolutely *is* a name for the
corresponding object. (This terminology has precedent.) But a 'yes'
answer, if you also reject 'variable', means you no longer have an
agreed-upon term for the names that are defined in the current scope --
and such a term is a really good thing to have! (<cheeky>I know, let's
call them variables. :)</cheeky>)

Evan


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

iQEVAwUBUDaC4AOzoR8eZTzgAQLtugf/bwqcJWHF/F3PmXRQJeA8sCGSf/T0tHOy
cnHFgerCkO7+5f/TocEzHYCmII5E0mV0aK9LITv0mnYtFXubtZOXxH5RIZoSMs/4
J9+nvzszfABQm2zU26mC1HBk5xt8R36bL5dEm26916x9k8Q8mrbV6qlFw8TKB+xF
Yia24Wee/4/5ljaqXIN5gQkMSNfRy2edN6VRlz2Et6Ksox3LC7BdeJkWqa5lezuK
nG0ofqq9N5vQH80/eljNMlGErygWoI8ysB3x6pty5P8Ee48fxbeK1vGpJxFlt4i4
8dhDxUSW1hW2+AjlEw1GuVWyMJZ3m2KBfj5K9Xol9KXP9OnWn6pnNA==
=ivzE
-----END PGP SIGNATURE-----
 
J

Jan Kuiken

On 8/23/12 20:17 , Ian Kelly wrote:

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

Bare with me, i come from a C world, and think of each variable,
whatever its name or scope, as a piece of memory and therefore
different.
btw. I like the idea of simultaneously instantiation :)

Jan Kuiken
 
C

Chris Angelico

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.

Yet Python's variables are extremely close to C's pointer variables.
If you allocate all your "real data" on the heap and do everything
with pointers, you'll have semantics very similar to Python's (except
that things aren't refcounted, so you have massive memory leaks). In
fact, that's how the Python-C API handles things - a PyObject*
basically _is_ a Python object, as far as C's concerned.

But again, that probably doesn't help explain the variables. Unless
you've come from (or can at least imagine) an environment in which you
use pointers for *everything*.

ChrisA
 
C

Chris Angelico

In Python--, any time you use a name, you have to prefix it with the
word 'variable':
variable x = 4
print(variable x)

That gets really unwieldy. You should shorten it to a single symbol.
And your language could be called Python Hypertext Preprocessor.

ChrisA
 
D

Dennis Lee Bieber

Incidentally, I also realized another reason I don't like the 'names'
description. Take 'foo.bar'. (That is, the 'bar' attribute in object
'foo'.) Is 'foo.bar' a name? I'm not sure what the 'names' proponents
would say, but to me both answers are problematic. I *really* dislike a
'no' answer because to me, 'foo.bar' absolutely *is* a name for the
corresponding object. (This terminology has precedent.) But a 'yes'
answer, if you also reject 'variable', means you no longer have an
agreed-upon term for the names that are defined in the current scope --
and such a term is a really good thing to have! (<cheeky>I know, let's
call them variables. :)</cheeky>)

Let me complicate that... <G>

It is a fully qualified name when one wishes to work with the
entirety of the object the name is bound to... It is a partially
qualified name with respect to any sub-components of that object.
 
D

Dennis Lee Bieber

But again, that probably doesn't help explain the variables. Unless
you've come from (or can at least imagine) an environment in which you
use pointers for *everything*.
... but can not manipulate the pointer directly <G>
 
C

Chris Angelico

... but can not manipulate the pointer directly <G>

Right, obviously pointer arithmetic doesn't make sense in Python. But
that's (almost) guaranteed by the fact that there is NOTHING you can
do with bare integers.

foo q = new q; /* note that 'foo' is a typedef that hides the asterisk */
foo w = q +1; /* Pointer arith! Impossible. */

But!

foo e = q + one; /* one is the object representing the integer 1 */

This isn't pointer arithmetic. No C compiler will let you add two
pointers. You can subtract one from another, but you get back a bare
integer, which won't go into a 'foo', so the only thing you could do
that would break stuff is:

foo r = q + (w - e); /* Syntactically valid */

So you just won't do pointer arith if everything's a pointer.

There, I think I just broke a few minds. My task here is done.

ChrisA
 
R

Roy Smith

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.[/QUOTE]

I'll take a shot at this.

When I execute:

a = 4

I'm doing two things. The first is to create an object of type int with
a value of 4. I think everybody is OK with that part. The confusing
part comes with the LHS.

In C, or Java, there's a container called "a" which holds a value. In
C, that value is the integer 4, in Java it's an Integer object (well, at
least I think it is, I've never fully groked how Java handles integers).

In Python, there is no container named "a". There is, however, a dict
which exists somewhere in python-space. You can get a reference to this
dict by calling globals(). What the assignment does is effectively:

globals()["a"] = 4

In fact, I can even write it that way and everything works:
42

Even id() thinks they're the same thing:
id(a) 1755402140
id(globals()["a"])
1755402140

But, notice what happens if I now assign something new to a:
1755403176

The id has changed! Now, we all know that the id of an object is its
memory address (that's not guaranteed, but in the standard C
implementation of Python, that's what it is).

Now, what if I do something similar in C:

#include <stdio.h>

main() {
int a = 40;
printf("a = %d, &a = %p\n", a, &a);
a = 99;
printf("a = %d, &a = %p\n", a, &a);
}

When I compile and run this, it prints:

a = 40, &a = 0x7fff1911f5bc
a = 99, &a = 0x7fff1911f5bc

Notice that the address of the variable "a" didn't change when I
assigned it a new value. That's what people mean when they say C has
variables and Python doesn't; it just binds names to values.
 
C

Chris Angelico

In fact, I can even write it that way and everything works:
globals()["a"] = 42
a
42

Even id() thinks they're the same thing:
id(a) 1755402140
id(globals()["a"])
1755402140

Ah, no. What you have there is actually id(4) and nothing to do with a at all.
But, notice what happens if I now assign something new to a:

1755403176

The id has changed! Now, we all know that the id of an object is its
memory address (that's not guaranteed, but in the standard C
implementation of Python, that's what it is).

And you now have id(123) - of course, it's possible for there to be
two integer objects with the value 123, but what I'm emphasizing is
that you're not looking at a here.
Now, what if I do something similar in C:

#include <stdio.h>

main() {
int a = 40;
printf("a = %d, &a = %p\n", a, &a);
a = 99;
printf("a = %d, &a = %p\n", a, &a);
}

When I compile and run this, it prints:

a = 40, &a = 0x7fff1911f5bc
a = 99, &a = 0x7fff1911f5bc

Notice that the address of the variable "a" didn't change when I
assigned it a new value. That's what people mean when they say C has
variables and Python doesn't; it just binds names to values.

Try this instead. It's C++ not C but a much closer match. You could
instead play with malloc if you want it to be C.

#include <stdio.h>

main()
{
int *a=new int(40);
printf("a = %d, id(a) = %p\n",*a,a);
a=new int(99);
printf("a = %d, id(a) = %p\n",*a,a);
}

I've not tested the code and may have a syntax issue with "new
int(40)" (who ever allocates a single int on the heap??) but you get
the idea. At no point do you ever look at, or need to look at, &a.
That's utterly irrelevant.

ChrisA
 
A

alex23

Even id() thinks they're the same thing:
id(a) 1755402140
id(globals()["a"])
1755402140

Ah, no. What you have there is actually id(4) and nothing to do with a atall.

Well, nothing expect for the fact that he's demonstrating Python
references and how they bind to objects. Sure, id() isn't doing any
lookup, but that's missing the point.
And you now have id(123) - of course, it's possible for there to be
two integer objects with the value 123, but what I'm emphasizing is
that you're not looking at a here.

But Roy's point was that referring to 'a' as a 'variable' makes no
sense, as it's not an allocated piece of memory. In fact, he even said
"the id of an object" and not "the id of 'a'" so I'm not entirely sure
what you're objecting to here. You don't need to emphasise anything as
_that was the point_: you're _not_ looking at 'a' _ever_, you're only
ever looking at the object to which it refers.
 
A

Antoon Pardon

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).

The documentation unfortunately calls these references “variables†in
various places, which IMO compounds the confusion in newcomers
experienced with other languages. It's best, I think, to reject the idea
that Python has variables, and think in terms of references instead.
Why should we reject the idea that python has variables? Python
variables are a lot like scheme or smalltalk variables and I never
heard anyone having a problem considering these languages
having variables.
 
A

Antoon Pardon

Why should we reject the idea that python has variables? Python
variables are a lot like scheme or smalltalk variables and I never
heard anyone having a problem considering these languages
having variables.
Never mind. I missed the reactions already dealing with this.
 
E

Evan Driscoll

But Roy's point was that referring to 'a' as a 'variable' makes no
sense, as it's not an allocated piece of memory.

Does the computer just remember what 'a' refers to by keeping notes
about it in Narnia?

Put it this way. If C removed the & operator -- and thus you couldn't
tell what address a variable (or "variable instance", if you prefer) was
at -- would "int x;" cease to be a variable?

Evan



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

iQEcBAEBAgAGBQJQN0X6AAoJEAOzoR8eZTzgh/UH/1SJ7jGF77RMix7+wrdBl83B
HdexeXuDCbksCM01vTUz1kSTxMzaBtZerNnHMHPMqsxaGXZyYq7uTBxoojFbIQpf
KrdWs7DoQ8gdAYD7iW0HMEGFZ7l+sIthKLWWWoTgn+cm9PZfZ0y7pdgcsAEqrsss
NctarCC4D2+l13ouwsq8adWenJ7mitDLVxm5x+5HEaXJ/KFkwPXo9GdxCvWIShht
NMznDuUzojf2hoUDL8NPfensDzvvaCE/jqflMP7BFkx4Ck5Sb619wEgLlxU0+GuJ
5zg9NhojbQ0QOuFqfFFNnJPNJwitdr1k70O8jgviZtJfFwxPf4V5s5aK9RKLPks=
=60tv
-----END PGP SIGNATURE-----
 
S

Steven D'Aprano

Does the computer just remember what 'a' refers to by keeping notes
about it in Narnia?

No. The compiler remembers the address of 'a' by keeping notes about it
somewhere in memory during the compilation process. When you run the
compiled program, there is no longer any reference to the name 'a'.

(Many compilers give you the option to keep variable names, but that's
additional debugging data, not an essential part of the execution model.)

The mapping of name:address is part of the *compilation* process -- the
compiler knows that variable 'x' corresponds to location 12345678, but
the compiled code has no concept of anything called 'x'. It only knows
about locations. The source code 'x = 42' is compiled into something like
'store 42 into location 12345678'. (Locations may be absolute or
relative.)

In languages with name bindings, the compiler doesn't need to track
name:address pairs. The compiled application knows about names, but not
about addresses. The source code 'x = 42' is compiled into something like
'store 42 into the namespace using key "x"'.

Python gives you no way to peek at an address. It's not even clear what
the address of the variable would be, because there are *at least three*
things it could be:

1) the address of the key field in the namespace (where the name lives);

2) the address of the value field in the namespace (where the pointer to
the object lives);

3) the address of the object itself.

And any of these are free to move around during the lifetime of the
application. (E.g. in Jython, which runs under the JVM, objects don't
have a fixed location.)

Put it this way. If C removed the & operator -- and thus you couldn't
tell what address a variable (or "variable instance", if you prefer) was
at -- would "int x;" cease to be a variable?

Not at all. Just because the public interface of the language doesn't
give you any way to view the fixed locations of variables, doesn't mean
that variables cease to have fixed locations.
 
S

Steven D'Aprano

The id has changed! Now, we all know that the id of an object is its
memory address (that's not guaranteed, but in the standard C
implementation of Python, that's what it is).

It's not only "not guaranteed", it is *explicitly* noted as an
implementation detail. The id of the object is an arbitrary number
guaranteed to be unique during the lifetime of that object. It just
happens that CPython currently uses the memory address as the id. Jython
does not:

steve@runes:~$ jython
Jython 2.5.1+ (Release_2_5_1, Aug 4 2010, 07:18:19)
[OpenJDK Client VM (Sun Microsystems Inc.)] on java1.6.0_18
Type "help", "copyright", "credits" or "license" for more information.1


Nor does IronPython:

steve@runes:~$ ipy
IronPython 2.6 Beta 2 DEBUG (2.6.0.20) on .NET 2.0.50727.1433
Type "help", "copyright", "credits" or "license" for more information.43
 
A

Alexander Blinne

Or, at an even lower level...

Convert the decimal literal "1" to binary (including type casting)
to the predeclared type given to the variable "x", and store that binary
value into the predetermined memory associated with "x".

Not really the way i would view it. The conversion to binary of the
string "1" is part of the parsers and compilers work in order to do what
the language reference says about the meaning of x=1;. The resulting
code would simply store the binary value of an integer 1 (which is
contained in the code as is, nothing has to be converted or typecasted)
into the location corresponding to the variable x. So in C x=1; really
means store integer 1 to the variable x.
 
G

Grant Edwards

No. The compiler remembers the address of 'a' by keeping notes about it
somewhere in memory during the compilation process.

Ah, but as we are always fond of saying in this group "that's an
implementation detail, and not part of the language definition". The
model where a compiler is "keeping notes about it in Narnia" is also
perfectly valid. However, RAM is easier to find than magic wardrobes,
so the "notes" are usually kept in RAM these days.
 
C

Chris Angelico

Ah, but as we are always fond of saying in this group "that's an
implementation detail, and not part of the language definition". The
model where a compiler is "keeping notes about it in Narnia" is also
perfectly valid. However, RAM is easier to find than magic wardrobes,
so the "notes" are usually kept in RAM these days.

Maybe, but once you found that wardrobe, you'd have enough storage for
all your needs, AND it takes no time at all to retrieve it! I think we
should start developing NarPy at once.

ChrisA
 
S

Steven D'Aprano

So first, to some extent that's like saying "these two different things
are different in this important way, but other than that, what's the
difference?" :)

Yes, exactly. I acknowledge a difference between the two, and ask you
what differences you see.

Many languages do not have "first-class functions" -- you cannot pass a
function to another function as an argument, or generate them on the fly
at runtime. But the ability of functions to be treated as data is not an
essential part of being-a-function, so I see no problem with describing
both Pascal functions and Python functions as functions.

Likewise, being able to pass classes around as data and generate them on
the fly is not an essential part of being-a-class, to I see no problem
with describing both Java classes and Python classes as classes.

But there are some other differences. (Not all of these are strictly
with classes per se, but I would say they all have strong interactions
with the object system.)

I don't believe that any of those differences in behaviour are either
critical, or (as you acknowledge) strictly in the concept of *class*
itself. I think they're interesting differences, but I don't think they
are essential to the nature of "classness" in the same way that having a
fixed memory address is essential to the nature of "memory location
variable" or a name in a namespace is essential to "name binding
variable".


[...]
OK, let's make a new language. I'll call it 'Python--' because at least
*I* wouldn't want to program in it. :)

In Python--, any time you use a name, you have to prefix it with the
word 'variable':
variable x = 4
print(variable x)

Does Python-- have variables?

Of course, because that's what Python-- calls them. Whether Python-- is
*justified* in calling them variables is a more interesting question.

I think it is, in the sense that name bindings are a kind of variable,
and fixed memory locations are a different kind of variable. But I also
think that it isn't, for exactly the reasons why I prefer to describe
Python (without the minuses) as having name bindings rather than
variables "in the C or Pascal sense".

Ultimately what is important are the semantics of the words, not the
words themselves. Objections to use of "variable" are, I believe,
*pragmatic* objections that the word comes with too much baggage to be
safe to use, not that name bindings aren't a type of variable.

Think of it as duck-typing the term "variable". :) To me, Python locals
and globals look and quack like a variable.

And so they should, since name bindings are a way of implementing the
abstract Variable kind, so to speak.

Incidentally, I also realized another reason I don't like the 'names'
description. Take 'foo.bar'. (That is, the 'bar' attribute in object
'foo'.) Is 'foo.bar' a name?

Is "Evan Driscoll" a name? Or is it two names?

There is no contradiction to say that "Evan Driscoll" is both a name (a
"compound name", if you like, or fully-qualified name) and two names (a
personal name plus a family name).

foo.bar is both a fully-qualified name and two names: the name of the
namespace and the name of the attribute in the namespace.

I'm not sure what the 'names' proponents
would say, but to me both answers are problematic. I *really* dislike a
'no' answer because to me, 'foo.bar' absolutely *is* a name for the
corresponding object. (This terminology has precedent.) But a 'yes'
answer, if you also reject 'variable', means you no longer have an
agreed-upon term for the names that are defined in the current scope

"Local names".

We also have "global names" for those in the global scope, "builtin
names" for those in the built-ins, and "nonlocal names".
 

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

No members online now.

Forum statistics

Threads
473,774
Messages
2,569,598
Members
45,157
Latest member
MercedesE4
Top