Are Python variables pointers? Or else, what are they?
We call them references. They work like this
i = 5 # create int(5) instance, bind it to i
j = i # bind j to the same int as i
j = 3 # create int(3) instance, bind it to j
print i # i still bound to the int(5), j bound to the int(3)
Small ints are interned, but that isn't important to this explanation
i = [1,2,3] # create the list instance, and bind it to i
j = i # bind j to the same list as i
i[0] = 5 # change the first item of i
print j # j is still bound to the same list as i
In Python, are all variables void pointers?
The correct explanation really is that: Python has names, other languages have variables. What this means is that Python's variables are recovered by looking up their name in a dict at runtime.
Although, I'll give you that in my early Python days I too found this explanation disappointing. What I would have liked at the time would have been examples of what this implies for the developper.
Variables are in a dict
In lower-level languages, a variable's name is thrown away and replaced by an address in memory by the compiler. This is not the case in Python, which allows you to access all variables with the vars
builtin that returns the dict of the scope's variable.
This means you can read variables from that dict.
foo = 1
vars()['foo'] # 1
And that you can update and even declare a variable using this dict.
vars()['bar'] = 1
bar # 1
It also means you can list all variables in scope.
foo = 1
bar = 1
vars().keys() # ['__name__', '__doc__', ... , 'foo', 'bar'])
The NameError
exception
In C, accessing a variable that has not been declared is a compile error. In Python, since variables' names are looked up in a dict, it is a runtime exception that can be caught like any exception.
try:
print(foo)
except NameError:
print('foo does not exist') # This is printed
There are no pointers
In Python, the whole mechanic of accessing a value by its position in memory is hidden from you. Your way to access a variable is by knowing its name.
In particular this means that you can delete a name and prevent all access whatsoever to its value.
foo = object()
del foo
# The above object is now completely out of reach
What the above does is remove the 'foo'
key in the vars()
dict.
Understanding pointers and merging lists in python
Every Python variable is a reference to a value; if you already understand how pointers work in C, then it might be useful to think of variables which reference mutable objects as working like C pointers. They aren't really the same thing, but a Python variable that references a ListNode
acts a lot more like a C ListNode*
than a C ListNode
, so the pointer metaphor is a good conceptual starting point if that's the language you're coming from.
dummy
always points to the node that you created in the first line of the function, which is the same node thatcur
starts at. The first time you updatecur.next
, you are also updatingdummy.next
.cur
is then reassigned to a new node, but the modification you made todummy
persists.
This Python code:
cur = dummy = ListNode()
while list1 and list2:
if list1.val < list2.val:
cur.next = list1
list1, cur = list1.next, list1
is essentially the same as:
ListNode* cur, dummy;
cur = dummy = new ListNode();
while (list1 && list2) {
if (list1->val < list2->val) {
cur->next = list1;
cur = list1;
list1 = list1->next;
}
}
- One is modifying the
next
attribute of the node thatcur
points to; the other is modifyingcur
itself to point at a new node.
cur.next = list2
cur = cur.next
is the same as:
cur->next = list2;
cur = cur->next;
For a more in-depth explanation of how exactly variables work in Python, read https://nedbatchelder.com/text/names.html
Python variables under the hood
Not really, but close. A Python variable is a name that refers to an object. Full stop. Python doesn't define any semantics about how this is done.
print
takes an object as its argument. That object can be passed via a literal (print(3)
,print("foo")
,print(True)
), or via a reference (print(a)
).id
returns an integer identifier that is unique to that object for the lifetime of that object. What that integer is is also not defined by the language; it's up to the implementation to decide. It could just as easily be a serial number that starts with 0 and gets incremented every time a new object is created.
Any question about "under the hood" can only be answered by specifying which implementation of Python you are using, and that answer will not really be of any use in understanding what a particular piece of Python means, only in understanding how a particular implementation does it.
how python variable works?
What you're seeing is an optimization detail of CPython (the most common Python implementation, and the one you get if you download the language from python.org).
Since small integers are used so frequently, CPython always stores the numbers -5 through 256 in memory, and uses those stored integer objects whenever those numbers come up. This means that all instances of, say, 5
will have the same memory address.
>>> a = 5
>>> b = 5
>>> id(a) == id(b)
True
>>> c = 4
>>> id(a) == id(c)
False
>>> c += 1
>>> id(a) == id(c)
True
This won't be true for other integers or non-integer values, which are only created when needed:
>>> a = 300
>>> b = 300
>>> id(a) == id(b)
False
Pointers in Python?
There's no way you can do that changing only that line. You can do:
a = [1]
b = a
a[0] = 2
b[0]
That creates a list, assigns the reference to a, then b also, uses the a reference to set the first element to 2, then accesses using the b reference variable.
Related Topics
How to Filter Only Printable Characters in a File on Bash (Linux) or Python
How Remove Camera Preview to Raspberry Pi
To Read Line from File Without Getting "\N" Appended at the End
Construct Pandas Dataframe from Items in Nested Dictionary
How to Create a Zip Archive of a Directory
I Can't Install Pyaudio on Windows? How to Solve "Error: Microsoft Visual C++ 14.0 Is Required."
Split String on Whitespace in Python
Regular Expression to Return Text Between Parenthesis
Simple Prime Number Generator in Python
Threading.Timer - Repeat Function Every 'N' Seconds
Problem Running Python from Crontab - "Invalid Python Installation"
Unicode Box Drawing Characters Not Printed in Ruby
Scheduling a Regular Event: Cron/Cron Alternatives (Including Celery)
"Ssl Module in Python Is Not Available" When Installing Package with Pip3
Is _Init_.Py Not Required for Packages in Python 3.3+
Python: Removing List Element While Iterating Over List
How to Run Functions in Parallel
How to Remove the Ansi Escape Sequences from a String in Python