Author Topic: Oh boy, adventures in rebinding variables!!! (Python)  (Read 31980 times)

Gr3yling

  • Rogueliker
  • ***
  • Posts: 168
  • Karma: +0/-0
    • View Profile
    • Email
Oh boy, adventures in rebinding variables!!! (Python)
« on: May 17, 2014, 02:51:41 AM »
That sounds like a fantastic name for a roguelike, incidentally.

So, I'm having a number of problems, and I suspect they are related to my limited understanding of how variables are bound and re-bound.  I don't understand why the following code:

count = 0

def increment(x):
    global x

Aukustus

  • Rogueliker
  • ***
  • Posts: 440
  • Karma: +0/-0
    • View Profile
    • The Temple of Torment
Re: Oh boy, adventures in rebinding variables!!! (Python)
« Reply #1 on: May 17, 2014, 11:14:30 AM »
I'm wondering if there's some missing words in your post here: "I don't understand why the following code:". Does what?

Zireael

  • Rogueliker
  • ***
  • Posts: 604
  • Karma: +0/-0
    • View Profile
Re: Oh boy, adventures in rebinding variables!!! (Python)
« Reply #2 on: May 17, 2014, 04:35:48 PM »
"... doesn't work" most probably  ;)

Gr3yling

  • Rogueliker
  • ***
  • Posts: 168
  • Karma: +0/-0
    • View Profile
    • Email
Re: Oh boy, adventures in rebinding variables!!! (Python)
« Reply #3 on: May 18, 2014, 02:00:11 AM »
Okay, I have no idea how this got posted.  The forum interface was acting wonky so I decided to give up and post my question later.  Sorry.  I didn't realize it actually got submitted.

Suffice to say I've been having a lot of trouble with understanding how variables are bound in Python.  Before you link me to the python documentation, let me just say that I have definitely looked there extensively (and a lot of other tutorials).

There are a number of things I'm having a hard time getting, but lets start with this one:

x = 5

def test_function():
    x = 5
    return id(x)

print test_function()

print id(x)

Output: 31292720  and 31292720


WAAAAAT?  Aren't id's in CPYTHON memory addresses?  So, why do both x's have the same memory address?  I thought the whole point of all this crazy global and local variable stuff was that even though a variable might have the same name inside and outside of a function, it was NOT really the same variable unless global was called.  And my understanding is that if two variables have identical memory addresses, they meet the strictest quality for being identical (i.e. x(1) IS x(2), not just x(1) == x(2)).

I've got a lot of other questions but this is the one that's bugging me most right now.

I bought "Python in a Nutshell", and it's a bit over my head.  "Introduction to Python" (by O'Reily) should be here soon, so maybe I'll do better once I get started on it.

chooseusername

  • Rogueliker
  • ***
  • Posts: 329
  • Karma: +0/-0
    • View Profile
    • Email
Re: Oh boy, adventures in rebinding variables!!! (Python)
« Reply #4 on: May 18, 2014, 05:33:47 AM »
There are a number of things I'm having a hard time getting, but lets start with this one:

x = 5

def test_function():
    x = 5
    return id(x)

print test_function()

print id(x)

Output: 31292720  and 31292720


WAAAAAT?  Aren't id's in CPYTHON memory addresses?  So, why do both x's have the same memory address?  I thought the whole point of all this crazy global and local variable stuff was that even though a variable might have the same name inside and outside of a function, it was NOT really the same variable unless global was called.  And my understanding is that if two variables have identical memory addresses, they meet the strictest quality for being identical (i.e. x(1) IS x(2), not just x(1) == x(2)).

I've got a lot of other questions but this is the one that's bugging me most right now.
The id value is the memory address, but looking for patterns is meaningless.  You can easily modify your code to prove that both x's are different independent variables.

Look, if you really want to know, lower integer values are constants.  You can see this by doing:
Code: [Select]
i = 5
id(i)
i += 1
id(i)
Note that there will be different id's.  When you're dealing with classes and class instances, the id will of course be persistent and reliable.  But basing your code on requiring ids to work in some arbitrary way you picture they should work, will only lead to disappointment.

This is actually a considerable memory saving, that the lower integers work this way.  I saw the numbers when the patch was proposed.

Gr3yling

  • Rogueliker
  • ***
  • Posts: 168
  • Karma: +0/-0
    • View Profile
    • Email
Re: Oh boy, adventures in rebinding variables!!! (Python)
« Reply #5 on: May 18, 2014, 06:00:39 AM »
But I still don't understand how the two x's are independent if they but refer to the same memory address, presumably storing the same value.  Like I said, I thought that in the most fundamental way, the memory address *was* the identity of a variable. 

chooseusername

  • Rogueliker
  • ***
  • Posts: 329
  • Karma: +0/-0
    • View Profile
    • Email
Re: Oh boy, adventures in rebinding variables!!! (Python)
« Reply #6 on: May 18, 2014, 07:32:42 AM »
But I still don't understand how the two x's are independent if they but refer to the same memory address, presumably storing the same value.  Like I said, I thought that in the most fundamental way, the memory address *was* the identity of a variable.
If there is an optimisation that lower integers of the same value are the same object, then your two independent variables will point to the same object and have the same id which will be the address of that object.  Making common objects (like read only strings, or in this case a small set of the most commonly used integers) shared isn't an optimisation which Python alone uses.

TLDR: The id is the memory address of the actual object you are dealing with, not the memory address of the pointer to that object. 

Gr3yling

  • Rogueliker
  • ***
  • Posts: 168
  • Karma: +0/-0
    • View Profile
    • Email
Re: Oh boy, adventures in rebinding variables!!! (Python)
« Reply #7 on: May 18, 2014, 08:29:06 AM »
I thought Python didn't use pointers:

http://stackoverflow.com/questions/3106689/pointers-in-python

This topic starts with the statement: " I know python doesn't have pointers, but..."

So what gives?  Your answers are leaving me with more questions than solutions.

Sorry, I really do appreciate you (and the others who replied) taking the time to answer my question.  I just wish I understood enough to write the game I want to make.  I'm not trying to be difficult, it just seems that python can be very inconsistent sometimes. 

chooseusername

  • Rogueliker
  • ***
  • Posts: 329
  • Karma: +0/-0
    • View Profile
    • Email
Re: Oh boy, adventures in rebinding variables!!! (Python)
« Reply #8 on: May 18, 2014, 08:54:51 AM »
I thought Python didn't use pointers:

http://stackoverflow.com/questions/3106689/pointers-in-python

This topic starts with the statement: " I know python doesn't have pointers, but..."

So what gives?  Your answers are leaving me with more questions than solutions.

Sorry, I really do appreciate you (and the others who replied) taking the time to answer my question.  I just wish I understood enough to write the game I want to make.  I'm not trying to be difficult, it just seems that python can be very inconsistent sometimes.
Your problem is that I am explaining id() in terms of why it gives the values it does.  Python does not have pointers.

The fact is that id() is not something you should really ever use, and getting stuck on understanding it, is like getting stuck on why grass is pointed when you're mowing the lawn.  You can forget about the points on the blades of grass and keep mowing,  much the same as you can forget id() and learn and write top level Python code.  In fact, I suspect that most anyone who used id() would be writing low quality Python code.

Gr3yling

  • Rogueliker
  • ***
  • Posts: 168
  • Karma: +0/-0
    • View Profile
    • Email
Re: Oh boy, adventures in rebinding variables!!! (Python)
« Reply #9 on: May 18, 2014, 09:15:22 AM »
The fact is that id() is not something you should really ever use, and getting stuck on understanding it, is like getting stuck on why grass is pointed when you're mowing the lawn.  You can forget about the points on the blades of grass and keep mowing,  much the same as you can forget id() and learn and write top level Python code.  In fact, I suspect that most anyone who used id() would be writing low quality Python code.

Dood, I write the *LOWEST* quality python code right now.  I have been trained most of my life for something vastly different than understanding computer science, and the reason that I'm posting here is so that I want to write just barely less low quality code than that which you are referring to. 

Look, I know it seems weird, but the best way I seem to understand things is in a bottom-up sort of way, where there slightly less complicated concepts build on the most complicated concepts. 

tl:dr (even though I do read all of what *you* post when you say tl:dr) I'm trying to learn about computer science coming from a completely different dimension than most of those who study it.  Please be patient with me.

Xecutor

  • 7DRL Reviewer
  • Rogueliker
  • *
  • Posts: 263
  • Karma: +0/-0
    • View Profile
Re: Oh boy, adventures in rebinding variables!!! (Python)
« Reply #10 on: May 19, 2014, 04:20:38 AM »
As far as I know internally everything in python is refcounted pointer. Even integers. Even None!
x=5
here compiler creates constant 5 during compile time, and simply assigns pointer to this constant to x, when executing this line.
and increment ref count.

id converts this internal pointer to integer. so all 5s in your program will have the same id.

array of equal integers is actually array of pointers pointing to one and the same piece of memory.

Gr3yling

  • Rogueliker
  • ***
  • Posts: 168
  • Karma: +0/-0
    • View Profile
    • Email
Re: Oh boy, adventures in rebinding variables!!! (Python)
« Reply #11 on: May 20, 2014, 12:53:57 AM »
Thanks for taking the time to answer my question, Xecutor.   I do believe that you know what you are talking about (and I actually suspected you would be someone who could help me) but it is confusing to hear some sources say that python does not use pointers, and then in this topic multiple people have said it does.  What is the cause of this discrepancy?

And just to be clear, the code I posted is not something I would use in my roguelike, I'm just trying to understand local/global variables so that I can get past where I am stuck right now.


Xecutor

  • 7DRL Reviewer
  • Rogueliker
  • *
  • Posts: 263
  • Karma: +0/-0
    • View Profile
Re: Oh boy, adventures in rebinding variables!!! (Python)
« Reply #12 on: May 20, 2014, 03:41:07 AM »
Thanks for taking the time to answer my question, Xecutor.   I do believe that you know what you are talking about (and I actually suspected you would be someone who could help me) but it is confusing to hear some sources say that python does not use pointers, and then in this topic multiple people have said it does.  What is the cause of this discrepancy?
Probably you are confusing talks about internals of python with talks about the language itself.
Statement 'python does not use pointers' probably means something like 'programming language Python does not have pointer type as part of the language'.
It's pretty much obvious, that internals of the language is full of pointers.

Quote
And just to be clear, the code I posted is not something I would use in my roguelike, I'm just trying to understand local/global variables so that I can get past where I am stuck right now.
It's pretty simple.
If you assign something to a variable in a body of a function, this variable is considered local, unless you explicitly declare it as global.
But you can read global variables in a function without declaring them as globals.

Trystan

  • Rogueliker
  • ***
  • Posts: 164
  • Karma: +0/-0
    • View Profile
    • my blog
Re: Oh boy, adventures in rebinding variables!!! (Python)
« Reply #13 on: May 20, 2014, 03:44:09 AM »
Because python understands that a five is a five is a five. They're immutable so it's okay for the Python runtime to say they're all the same. So if you create a bunch of fives, the runtime reuses the same one instead of creating new instances. It's just an optimization. If you create a bunch of compound objects (like a Player, Tile, or Point), then each will have it's own space in memory even if all the attributes are the same since those objects have mutable state.

Gr3yling

  • Rogueliker
  • ***
  • Posts: 168
  • Karma: +0/-0
    • View Profile
    • Email
Re: Oh boy, adventures in rebinding variables!!! (Python)
« Reply #14 on: May 20, 2014, 04:52:33 AM »
Ah, so it's a mutable/immutable thing.  Okay.  That makes sense, because tuples seem to behave the same way, based on my limited testing.

Lets walk through this just to makes sure I understand:

The first variable x gets bound to five.  This means 5 is used to generate a hash value (which is also 5, it seems based on testing), which python uses to decide what memory address to store the value '5' at.

Second variable x gets bound to five.  Now, I though that with a pointer, a new hash value was generated for a new memory address, and that address just stored the location of the first memory address and told the computer to look there next.

But is the following happening instead for the second x?: python generates an identical hash for the second x, linking both x's back to the same memory address containing the 5 value.

See the distinction I'm trying to understand?  With what I understand a pointer to be (and I may be totally wrong) is one address that just contains instructions which 'point' the program to another different address, but with what seems like it is happening in python, there is only one address that both variables refer to.

And you guys are saying that the process is different with mutables/immutables?  Which, if either, of the scenarios I described previously happens with each of those?

I know theses seem like odd questions, but I think about things in an odd way, and this really does help me.