A certainl part of an if() structure never gets executed.

  • Thread starter Íéêüëáïò Êïýñáò
  • Start date
S

Steven D'Aprano

On Mon, 17 Jun 2013 08:17:48 +0300, Îίκος wrote:

[...]
Very surprising.
a and b was *references* to the same memory address, it was like a
memory address having 2 names to be addresses as.

b = a name we use to address some memory location, do we agree on that?

So, b = 6, must have changed the stored value of its mapped memory
location, but given you example it seems its changing the mapping of b
to some other memory address.

I don't follow its act of course.


Let me explain how variables work in some other languages, and how they
work in Python. (And Ruby, and Java, and many others.)

In a language like Pascal, or C, the compiler keeps a table mapping
variable names to fixed memory addresses, like this:

Variable Address
======== =======
x 10234
y 10238
z 10242


Code like:

x := 42;
y := x + 1;


will get compiled into something that looks like this:

# Pseudo-code
STORE 42 AT ADDRESS 10234;
READ ADDRESS 10234;
STORE (LAST RESULT + 1) AT ADDRESS 10238;


The important thing is that memory addresses are known at compile time,
and at least in general, variables cannot move around in memory. Another
important thing is that assignment is copying:

x := y;

becomes:

READ ADDRESS 10234;
STORE (LAST RESULT) AT ADDRESS 10238;

which is equivalent to:

COPY ADDRESS 10234 TO ADDRESS 10238;

If, instead of an integer, x was an array of 1000 integers, all 1000
integers would need to be copied.

Now, in languages like Python, Ruby, Java, and many others, there is no
table of memory addresses. Instead, there is a namespace, which is an
association between some name and some value:

global namespace:
x --> 23
y --> "hello world"


In Python, namespaces are *dicts*, just like those you create with {}.

Code like:

x = 42
y = x + 1


is treated as:

# Pseudocode
create the object 42
bind it to the name 'x'
look up the name 'x'
add 1 to it
bind it to the name 'y'


where "bind" means to change the association in the namespace:

global namespace:
x --> 42
y --> 43


One important thing is that binding does *not* make a copy of the object.
Assignment is equally fast whether you have one int or a list or a
million ints. So code like this:

x = y

results in both names 'x' and 'y' being associated to the same object.
With ints, that's pretty boring, but for mutable objects like lists, it
means that you get two names for the same list:

py> x = []
py> y = x
py> y.append("Surprise!")
py> x
['Surprise!']


This sort of behaviour is trivial in languages with name-binding
semantics, like Python, but quite tricky in languages like Pascal. You
have to explicitly work with pointers or other indirect memory access,
leading to extra effort and the possibility of serious bugs.

Note also that because you aren't dealing with fixed memory addresses,
objects are free to be moved in memory for better memory usage and less
fragmentation. CPython doesn't do this, but PyPy does, and I expect that
both Jython and IronPython probably do too. So long as the runtime
environment can (somehow) track when objects are moved, it all works out
fine.

Another difference is that in C-like languages, variables always have a
value, even if it's not a useful value. As soon as the compiler decides
that variable 'z' will be at address 10242, then 'z' has an implied value
made up of whatever junk happens to be at that address. Some compilers
will warn you if you try to use a variable without assigning to it first,
since using junk you happen to find lying around in memory is usually a
bad thing, but not all compilers.

In contrast, Python doesn't have this issue. If you haven't assigned to
'z', then there is no such thing as 'z' in your namespace, and trying to
use it will automatically give you an error:

py> x = z - 1
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'z' is not defined


There are other differences in regards to passing arguments to functions.
I've written about that before:

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

Michael Weylandt

Very surprising.
a and b was *references* to the same memory address, it was like a memory address having 2 names to be addresses as.

b = a name we use to address some memory location, do we agree on that?

So, b = 6, must have changed the stored value of its mapped memory location, but given you example it seems its changing the mapping of b to some other memory address.

I don't follow its act of course.

I'm having trouble understanding your grammar in the above, but please re-read my note on the dual behavior of `=` here:

http://mail.python.org/pipermail/python-list/2013-June/649990.html

Michael
 
S

Simpleton

Now, in languages like Python, Ruby, Java, and many others, there is no
table of memory addresses. Instead, there is a namespace, which is an
association between some name and some value:

global namespace:
x --> 23
y --> "hello world"

First of all thanks for the excellent and detailed explanation Steven.

As for namespace:

a = 5

1. a is associated to some memory location
2. the latter holds value 5

So 'a', is a reference to that memory location, so its more like a name
to that memory location, yes? Instead of accessing a memory address with
a use of an integer like "14858485995" we use 'a' instead.

So is it safe to say that in Python a == &a ? (& stands for memory address)

is the above correct?

I say this because here you said that: Instead, there is a namespace,
which is anassociation between some name and some value:

When you say that you mean that a is associated to some value as in
memory location or to that memory location's address?
 
M

Michael Torrie

So is it safe to say that in Python a == &a ? (& stands for memory address)

is the above correct?

It might be partially equivalent inside the interpreter, but it's not
something you should concern yourself with. And in general, no it's not
safe to say, since Python is a reference-counted, garbage-collected
object system and pointers in C certainly are not.
I say this because here you said that: Instead, there is a namespace,
which is anassociation between some name and some value:

When you say that you mean that a is associated to some value as in
memory location or to that memory location's address?

In python just think of assignment as making a name *be* an object. And
if you assign one name to another name, that makes both names be the
same object. When names are unbound (either they go out of scope or you
manually unbind them), the objects they are bound to are garbage collected.

Forget about the details of how the interpreter might doing at a low level.
 
T

Terry Reedy

First of all thanks for the excellent and detailed explanation Steven.

As for namespace:

a = 5

1. a is associated to some memory location
2. the latter holds value 5

This is backwards. If the interpreter puts 5 in a *permanent* 'memory
location' (which is not required by the language!), then it can
associate 'a' with 5 by associating it with the memory location. CPython
does this, but some other computer implementations do not.
So 'a', is a reference to that memory location, so its more like a name
to that memory location, yes? Instead of accessing a memory address with
a use of an integer like "14858485995" we use 'a' instead.

So is it safe to say that in Python a == &a ? (& stands for memory address)

is the above correct?

When you interpret Python code, do you put data in locations with
integer addresses?
 
S

Simpleton

In python just think of assignment as making a name *be* an object. And
if you assign one name to another name, that makes both names be the
same object. When names are unbound (either they go out of scope or you
manually unbind them), the objects they are bound to are garbage collected.

"Object" here being the memory location, right?
When we say a = 5

a = an easy way for calling that "fixed memory location" that holds our
value, instead of calling it in binary format or in hex format.
This is the direct object a is pointing too. Correct?

5 = *this* is the indirect object that a outputs when we print a.

Are the above statements correct Michael?

a = 5
b = a

a <---> memory address
b <---> memory address

I like to think a and b as references to the same memory address
 
S

Simpleton

This is backwards. If the interpreter puts 5 in a *permanent* 'memory
location' (which is not required by the language!), then it can
associate 'a' with 5 by associating it with the memory location. CPython
does this, but some other computer implementations do not.

Please tell me how do i need to understand the sentence
'a' is being associated with number 5 in detail.

Why don't we access the desired value we want to, by referencing to that
value's memory location directly instead of using namespaces wich is an
indirect call?

i feel we have 3 things here

a , memory address of a stored value, actual stored value
When you interpret Python code, do you put data in locations with
integer addresses?

I lost you here.
 
B

Benjamin Kaplan

Please tell me how do i need to understand the sentence
'a' is being associated with number 5 in detail.

Why don't we access the desired value we want to, by referencing to that
value's memory location directly instead of using namespaces wich is an
indirect call?

i feel we have 3 things here

a , memory address of a stored value, actual stored value



I lost you here.

You're confusing the way in which the CPython interpreter is written
with the way the Python language is defined. Yes, the CPython
interpreter puts 5 into a numbered memory location when creating the
object. But the Nikos Python Interpreter (which is a completely valid,
although quite buggy, Python interpreter that uses your head to
interpret the code) should not be using numbered memory locations.

Forget about memory locations. Memory locations don't exist. Let's use
the pen-and-paper Python interpreter. On the left side of the paper,
we'll write down the names. On the rest of the paper, we'll write down
the objects.

When I do "x =[]", I make a new list (which means I write down []
somewhere in the middle of the page), I create the name "x" (which
means I write down an "x" on the left side of the page), and then I
draw an arrow pointing from the x to the [].
(sorry if my drawing doesn't line up in your email/news client- I'll
try to make it line up correctly with a monospace font)
--------------------------------------------
| x --------------> [] |
| |
| |
--------------------------------------------

Now, When we do y = x, the right side of the equation is evaluated
(which gives us the object currently bound to the name x) and it is
then given the newly created name "y"
--------------------------------------------
| x --------------> [] |
| ^ |
| y ----------------| |
--------------------------------------------

When we do x.append(3), the object that x refers to is modified. This
is seen by both x and y because they point to the same object.

--------------------------------------------
| x --------------> [3] |
| ^ |
| y ----------------| |
--------------------------------------------

When I do x = [], a new object is created somewhere else on the page,
and the name x is made to point to the new object. This changes the
arrow. The name "x" is not in any way tied to the location of the [3]
on the page. This doesn't impact "y" which is still pointing at the
same spot it was before

--------------------------------------------
| x -------->[] [3] |
| ^ |
| y ----------------| |
--------------------------------------------

That is how Python's object model works. In CPython, objects have
specified memory locations but names do not. In IronPython and Jython,
even that's not guaranteed- the garbage collector can move the objects
around during their lifetime, so while you can trust that a name will
always point to the correct object, you have no guarantee about where
the object is located in the computer's memory.
 
J

Joel Goldstick

Please tell me how do i need to understand the sentence
'a' is being associated with number 5 in detail.

Why don't we access the desired value we want to, by referencing to that
value's memory location directly instead of using namespaces wich is an
indirect call?

i feel we have 3 things here

a , memory address of a stored value, actual stored value

So is it safe to say that in Python a == &a ? (& stands for memory

I lost you here.


Read and study this. Then come back and ask again. Don't think of
physical representation of memory with actual binary addresses. Python is
not assembler. Neither is it C (sometimes called high level assembler)
http://docs.python.org/2/tutorial/classes.html#python-scopes-and-namespaces
 
Î

Îίκος

Please tell me how do i need to understand the sentence
'a' is being associated with number 5 in detail.

Why don't we access the desired value we want to, by referencing to that
value's memory location directly instead of using namespaces wich is an
indirect call?

i feel we have 3 things here

a , memory address of a stored value, actual stored value



I lost you here.

You're confusing the way in which the CPython interpreter is written
with the way the Python language is defined. Yes, the CPython
interpreter puts 5 into a numbered memory location when creating the
object. But the Nikos Python Interpreter (which is a completely valid,
although quite buggy, Python interpreter that uses your head to
interpret the code) should not be using numbered memory locations.

Forget about memory locations. Memory locations don't exist. Let's use
the pen-and-paper Python interpreter. On the left side of the paper,
we'll write down the names. On the rest of the paper, we'll write down
the objects.

When I do "x =[]", I make a new list (which means I write down []
somewhere in the middle of the page), I create the name "x" (which
means I write down an "x" on the left side of the page), and then I
draw an arrow pointing from the x to the [].
(sorry if my drawing doesn't line up in your email/news client- I'll
try to make it line up correctly with a monospace font)
--------------------------------------------
| x --------------> [] |
| |
| |
--------------------------------------------

Now, When we do y = x, the right side of the equation is evaluated
(which gives us the object currently bound to the name x) and it is
then given the newly created name "y"
--------------------------------------------
| x --------------> [] |
| ^ |
| y ----------------| |
--------------------------------------------

When we do x.append(3), the object that x refers to is modified. This
is seen by both x and y because they point to the same object.

--------------------------------------------
| x --------------> [3] |
| ^ |
| y ----------------| |
--------------------------------------------

When I do x = [], a new object is created somewhere else on the page,
and the name x is made to point to the new object. This changes the
arrow. The name "x" is not in any way tied to the location of the [3]
on the page. This doesn't impact "y" which is still pointing at the
same spot it was before

--------------------------------------------
| x -------->[] [3] |
| ^ |
| y ----------------| |
--------------------------------------------

That is how Python's object model works. In CPython, objects have
specified memory locations but names do not. In IronPython and Jython,
even that's not guaranteed- the garbage collector can move the objects
around during their lifetime, so while you can trust that a name will
always point to the correct object, you have no guarantee about where
the object is located in the computer's memory.
EXCELLENT EXPLANATION, THANK YOU VERY MUCH.
I AM SAVING THIS TO A .TXT FOR FUTURE REFERENCE.

THAT'S WHY I ASK YOU GUYS FOR HUMAN LIKE EXPLANATIONS.
THIS CANNOT BE FIND WITH SUCH SIMPLE WAY OF PUTTING THIS IN TECH DOCS.

Something else please:

The way some info(i.e. a Unicode string) is saved into the hdd , is the
same way its being saved into the memory too? Same way exactly?

While you said to me to forget about memory locations, and that's indeed
made things easy to follow i still keep wondering, how Python internally
keeping tracks of 'x' and 'y' names as well as their referenced objects
(i.e. number 6).

After all the way i understand memory is as a series of bits like:

0100010100011110101000010101010010001001010010011100001101001010010

So from the above binary form:

what is 'x', what is 'y', how's 'x' and 'y' differ from the actually
memory locations that are bound too, and of course what is the actual value.

Its 3 things for me to consider, even in Python id internal level
detail. I want to understand this.

names, memory addresses, memory address's actual values

Thanks again Benjamin for making things clear.
 
T

Terry Reedy

Memory in biological brains is not a linear series of bits, or
characters. How we do associate things is still mostly a puzzle.

Read about holographic memory.
The way some info(i.e. a Unicode string) is saved into the hdd , is the
same way its being saved into the memory too? Same way exactly?

No. A unicode string is a sequence of abstract characters or codepoints.
They must be encoded somehow to map them to linear byte memory. There
are still (too) many encodings in use. Most cannot encode *all* unicode
characters.

CPython is unusual in using one of three different encodings for
internal unicode strings.
While you said to me to forget about memory locations,

This is excellent advice. One of the *features* of Python is that one
*can* forget about addresses. One of the *problems* of C is that many
people *do* forget about memory locations, while virus writers study
them carefully.
 
S

Steven D'Aprano

First of all thanks for the excellent and detailed explanation Steven.

As for namespace:

a = 5

1. a is associated to some memory location

No. a is associated to an object, the int 5, which may be free to move in
memory (PyPy does this), or may be at a fixed memory location (CPython
does this). But the association is with the object, not the memory
location.

The object is a data structure that contains a type (int), a value (5),
and various methods (e.g. bit_length, to_bytes).


2. the latter holds value 5
So 'a', is a reference to that memory location, so its more like a name
to that memory location, yes? Instead of accessing a memory address with
a use of an integer like "14858485995" we use 'a' instead.

No. We're talking about what the Python interpreter does, not what you
do. Whether you are programming in C or Python, you still refer to
variables by name:

a = 5

but what goes on inside the interpreter or compiler is different.

So is it safe to say that in Python a == &a ? (& stands for memory
address)

Absolutely not.

is the above correct?

I say this because here you said that: Instead, there is a namespace,
which is anassociation between some name and some value:

When you say that you mean that a is associated to some value as in
memory location or to that memory location's address?

No. This has nothing to do with memory locations. Namespaces are dicts.
Write down a dict:

{"a": "Hello world"}

Do you see a memory location there? There is no memory location. There is
the name, "a", and the object it is associated with, "Hello world".
Either the dict, or the string, may move around memory if the underlying
memory manager allows it. Obviously any object in Python must be
*somewhere* in memory at any specific moment, but that is irrelevant to
understanding Python code. It is no more relevant than saying that a dict
{'a': 5} is just made up of bits.
 
Î

Îίκος

Στις 18/6/2013 2:09 πμ, ο/η Steven D'Aprano έγÏαψε:
{"a": "Hello world"}

Do you see a memory location there? There is no memory location. There is
the name, "a", and the object it is associated with, "Hello world".
Either the dict, or the string, may move around memory if the underlying
memory manager allows it. Obviously any object in Python must be
*somewhere* in memory at any specific moment, but that is irrelevant to
understanding Python code. It is no more relevant than saying that a dict
{'a': 5} is just made up of bits.

Okey, the easy part was to understand how humans in high level need to
understand namespaces and assignment (which is not copying but instead
referencing another name to the same object).

But i would like to know, what happens internally within the python
compiler, because obviously memory is involved.

The way some info(i.e. a Unicode string) is saved into the hdd , is the
same way its being saved into the memory too? Same way exactly?

While you said to me to forget about memory locations, and that's indeed
made things easy to follow i still keep wondering, how Python internally
keeping tracks of 'x' and 'y' names as well as their referenced objects
(i.e. number 6).

After all the way i understand memory is as a series of bits like:

0100010100011110101000010101010010001001010010011100001101001010010

So from the above binary form:

what is 'x', what is 'y', how's 'x' and 'y' differ from the actually
memory locations that are bound too, and of course what is the actual value.

Its 3 things for me to consider, even in Python id internal level
detail. I want to understand this.

names, memory addresses, memory address's actual values
 
S

Steven D'Aprano

Στις 18/6/2013 2:09 πμ, ο/η Steven D'Aprano έγÏαψε:

Okey, the easy part was to understand how humans in high level need to
understand namespaces and assignment (which is not copying but instead
referencing another name to the same object).

But i would like to know, what happens internally within the python
compiler, because obviously memory is involved.

Depends which Python compiler.

CPython, IronPython, PyPy, Jython, Nuitka, Cython, ... ? They all operate
differently on the inside. Only the high-level Python code has to be the
same.

Jython works according to the JRE, the Java Runtime Environment. There is
masses of information about that on the Internet, google for it.

IronPython works according to the .Net runtime environment. Again, google
for it.

PyPy is a VERY complex but powerful JIT compiler. You can read about it
on the PyPy blog. Start here: http://morepypy.blogspot.com/

There's not a lot of documentation on how CPython works internally. You
have to read the C source code. You will need to understand about garbage
collectors, memory management, the difference between the stack and the
heap, etc. It's a big area to study. Don't expect anyone to spend the
days or weeks it will take to explain the whole thing.

The way some info(i.e. a Unicode string) is saved into the hdd , is the
same way its being saved into the memory too? Same way exactly?

No. Unicode strings can be stored on disk in any encoding you like.
Python stores string in memory as objects, which might look something
like this:

[Type=str, size=42, data=...]

only more complicated. And subject to change -- anything you learn that
holds for Python 3.3 might not apply for 3.2 or 3.4.

In Python 3.2 and older, the data will be either UTF-4 or UTF-8, selected
when the Python compiler itself is compiled. In Python 3.3, the data will
be stored in either Latin-1, UTF-4, or UTF-8, depending on the contents
of the string.

While you said to me to forget about memory locations, and that's indeed
made things easy to follow i still keep wondering, how Python internally
keeping tracks of 'x' and 'y' names as well as their referenced objects
(i.e. number 6).

Good question, but I don't have a good answer. It has to do with the
Python's memory manager, and the garbage collector. I don't know how they
work.


After all the way i understand memory is as a series of bits like:

0100010100011110101000010101010010001001010010011100001101001010010

So from the above binary form:

what is 'x', what is 'y', how's 'x' and 'y' differ from the actually
memory locations that are bound too, and of course what is the actual
value.

Its 3 things for me to consider, even in Python id internal level
detail. I want to understand this.

names, memory addresses, memory address's actual values


Start here:

https://duckduckgo.com/html/?q=how computers work
 
D

Dave Angel

<SNIP>

In Python 3.2 and older, the data will be either UTF-4 or UTF-8, selected
when the Python compiler itself is compiled.

I think that was a typo. Do you perhaps UCS-2 or UCS-4
 
D

Dennis Lee Bieber

But i would like to know, what happens internally within the python
compiler, because obviously memory is involved.
Fine... Download the Python SOURCE code, and read it...
 
S

Steven D'Aprano

In Python 3.2 and older, the data will be either UTF-4 or UTF-8,
selected when the Python compiler itself is compiled. In Python 3.3, the
data will be stored in either Latin-1, UTF-4, or UTF-8, depending on the
contents of the string.

UTF-4? UTF-8?

Whatever crack I was smoking, it obviously was *bad* crack.

That should be UTF-8 or UTF-16.
 
S

Steven D'Aprano

I think that was a typo. Do you perhaps UCS-2 or UCS-4

Yes, that would be better.

UCS-2 is identical to UTF-16, except it doesn't support non-BMP
characters and therefore doesn't have surrogate pairs.

UCS-4 is functionally equivalent to UTF-16, as far as I can tell. (I'm
not really sure what the difference is.)
 
S

Steven D'Aprano

UTF-4? UTF-8?

Whatever crack I was smoking, it obviously was *bad* crack.

That should be UTF-8 or UTF-16.

Good lord, that crack is worse than I thought.

UTF-16 and UTF-32.

Bloody hell. I am ashamed.
 
M

Marcin Szamotulski

While you said to me to forget about memory locations, and that's indeed
made things easy to follow i still keep wondering, how Python internally
keeping tracks of 'x' and 'y' names as well as their referenced objects
(i.e. number 6).

There is an excellent blog post about CPython internals:
http://tech.blog.aknin.name/category/my-projects/pythons-innards/
but it might be difficult to follow if you cannot at least read C.
It explains how python virtual machine works internally, how the opcodes
are evaluated, how the three scopes globals, locals and builins find its
place (and how names are bind). As far as I understand names are keys
in the scope dictionaries, which are exposed in the python level as
locals(), globals() and the builtin's. This is how Python tracks names
and their values. To be more precise, when you do:
.... b=2

in the first line 'a' is added to the globals() dictionary with value 1,
and in the third line 'b' with value 2 is added to the local dictionary
of f. It is also all explained in the python docs, and it reflects how
python is implemented (at least CPython).
After all the way i understand memory is as a series of bits like:

0100010100011110101000010101010010001001010010011100001101001010010

So from the above binary form:

what is 'x', what is 'y', how's 'x' and 'y' differ from the actually
memory locations that are bound too, and of course what is the actual value.

'x' and 'y' are just strings which are written somewhere in the computer's
memory.
Its 3 things for me to consider, even in Python id internal level
detail. I want to understand this.

names, memory addresses, memory address's actual values

Names and values are not connected through their memory addresses but
because they live in a higher structure, name is a key and value is a value
of a dictionary (which is also represented in some way at the C level,
namely by PyDictObject ... but for this you need to first learn C, but
please read and understand the Python docs - there is already a lot
there for you ...

Best regards,
Marcin
 

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,755
Messages
2,569,537
Members
45,021
Latest member
AkilahJaim

Latest Threads

Top