Can you hold pointers in a python list? - python

For example
b = 4
c = []
c.append(b)
print(c)
b += 2
print(c)
I was hoping I would get
4
6
but I got
4
4
Any chance I could add the element as a pointer. And then if I reference that element with c[0] I'd be referencing the b?

here c and b are different variables where c is list and b is int so if you add some on b it doesn't mean and c will be updated but if you add some number on b and append it again on c
there will be a change
b = 4
c = []
c.append(b)
print(c)
b += 2
c.append(c)
print(c)
and what you will get is
[4, 6]
and I think is clear that a c didn't change in your question

You can do that with a class:
class Number:
def __init__(self, number):
self.number = int(number)
def __str__(self):
return str(self.number)
def __repr__(self):
return self.__str__()
def __add__(self, other):
self.number = self.number + other
b = Number(4)
c = []
c.append(b)
print(c)
b += 2
print(c)
You will get:
4
6

Refer this below link to understand how the reference works in python:
How do I pass a variable by reference?
So, in short,
python objects i.e. booleans, integers, floats, strings, and tuples are immutable, which means that after you create the object and assign some value to it, you can't modify that value.
Hence, when you do b += 2, here, b will point to a new memory reference.
Proof:
>>> b=10
>>> id(b)
1734146112
>>> b+=2
>>> id(b)
1734146144
>>>
However, as #yoav mentioned above,
you can also do this by tweaking the default behaviour of Number class but beware; you should use it very carefully as you might not need this behaviour for every class.

Related

How is the assignment operator creating a deep copy?

Below is the code
a =2
b = a
b = 3
print (b,a)
3 2
I expect the value of a also to change to 3 , if b is only pointing to a's memory space and does not have it's own memory.
I am sure there is a very simple explanation which i am missing.
No. Assignment copies the reference to the object, not the object itself. eg
a = [1, 2, 3]
b = a
b[0] = 5
print(a) # gives [5, 2, 3]
However,
b = a
b = 3
re-assigns b to a new integer literal, having nothing to do with a.
Also, not strictly part of your question, but see the difference between mutable and immutable objects.
b = a points b to the same object as a. But then when you do b = 3 that reassigns b to point to a different object. a is not affected.
The problem here is that you think of python variables a pointers, where is not bad at all but they don't work like that. You should think of python variables as labels to values. Also you have to think about mutable and inmutable data. Python strings and integers are inmutable, that means that python creates a new number for each operation and reassigns the variable to the new number.
As in your example:
--------------------------------
| 3 | 2 | .. |
--------------------------------
a = 2 # a points to place 1 in our example memmory block
b = a # b points to the same memmory block as a
b = 3 # b change to point to the memmory block where 3 is located, place 0
In case that:
a = 2 # a points to place 1 in our example memmory block
b = a # b points to the same memmory block as a
b += 1 # b == 2, b + 1 == 3, so b will point to a 3, a is still not modified
if you reassign a value of b, python reassigns b which has a different value and memory loc. then. printing the address with id(a) and id(b) you can see that if values are different so the memory addresses are actually different.
try in python shell :
a = 3
b = a
id(b) == id(a) #it returns True
b = 2
id(b) == id(a) #it returns False

Python scoping in functions

Consider the following code:
>>> b = 3
>>> def change (b):
... b = 2
...
>>> change(b)
>>> print(b)
3
I am not confused by the fact that the print statement returns 3. Here's the question: is this because of scope, or because the argument that the function takes is not related to the outside b?
The b inside change is of a different scope than b outside of change. Inside the scope of the function, it does not matter what you call the variable before you pass it in - for now, it's going to be called b. As long as you don't return b from change and assign it to your "original" b, the first one won't change.
def change(b):
b = 2
return b
change(b)
print(b) # 3
b = change(b)
print(b) # 2
You are reassigning b. It does not change the parameter. You can test this using the id() function before and after the assignement.
The scope answers are partially correct for the object type you are passing.
Check out this link for information about how python "passes by value reference"
http://stupidpythonideas.blogspot.com/2013/11/does-python-pass-by-value-or-by.html
Here is another link that explains pythons Local -> Enclosed -> Global -> Built-in scope resolution with some examples:
http://nbviewer.ipython.org/github/rasbt/python_reference/blob/master/not_so_obvious_python_stuff.ipynb#python_legb
FWIW, the behavior is slightly different if we consider mutable objects:
>>> b = [3]
>>> def change(b):
... b[0] = 2
...
>>> change(b)
>>> print(b)
[2]
>>>
You have asked quite a tricky question, in the sense that the terminology you have used in framing the question is making people give you differing and weird answers.
You've given two choices:
we have a scope issue
b inside the function isn't related to b outside the function
Well, they are both true, and they are really just two ways to say the same thing.
Forgetting about terminology for a moment, realize that there is absolutely no difference between
b = 3
def f(a):
print(a)
f(b)
and
b = 3
def f(b):
print(b)
f(b)
The parameter names in a function's signature (the def line of a function) are local to the function, no matter what names are outside the function.
Now, you probably noticed that I sidestepped the issue of assignment within a function. That's because it's harder to explain quickly, but still be understandable and memorable to someone still in the fairly early stages of learning Python (which, no offense, it seems like you are).
Here is some reading that should help you understand fundamental concepts in Python:
http://nedbatchelder.com/text/names.html
http://www.jeffknupp.com/blog/2013/02/14/drastically-improve-your-python-understanding-pythons-execution-model/
You need to look at global variables. Just add global b at the beginning of your code and function, and it should work:
>>> global b
>>> b = 3
>>> def change():
... global b
... b = 2
...
>>> b
3
>>> change()
>>> b
2
>>>
You also need to remove the b parameter from def change(b), because that makes b both local and global. You can also return b:
>>> b = 3
>>> def change(b):
... b = 2
... return b
...
>>> b
3
>>> b = change(b)
>>> b
2
It is a scoping problem. b in the function is a local variable.
globals() is dictionary which hold all global variables.
b=3
def change (a):
globals()[a] = 2
print b
# 3
change("b")
print b
# 2

Python syntax clarification

Scrolling through the python 2.7 docs I came across this snippet
def fib(n): # write Fibonacci series up to n
a, b = 0, 1
while b < n:
print a,
a, b = b, a+b
But I don't understand the last line, and unsure of how I would google for it.
How should I read a, b = b, a+b, or, what does it mean ?
Python evaluates the right-hand side of assignments first. It evaluates
b, a+b
from left to right. It then assigns the values to the variables a and b respectively.
So a, b = b, a+b is equivalent to
c = b
d = a+b
a = c
b = d
except that it achieves the result without explicit temporary variables.
See the docs on Python's evaluation order.
There is a subtle point here worth examining with an example. Suppose a = 1, b = 2.
a, b = b, a+b
is equivalent to
a, b = 2, 1+2
a, b = 2, 3
So a gets assign to 2, b is assigned to 3.
Notice that this is not equivalent to
a = b
b = a + b
Since the first line would assign
a = 2
b = 2 + 2 = 4
Notice that done this (wrong) way, b ends up equal to 4, not 3. That's why it is important to know that Python evaluates the right-hand side of assignments first (before any assignments are made).
It is setting a to b, and b to a + b, without needing an intermediate variable. It could also be accomplished with:
temp = a
a = b
b = temp + b

How to access a variable defined inside a function from out side? [duplicate]

This question already has answers here:
How to get/set local variables of a function (from outside) in Python? [duplicate]
(5 answers)
Closed 9 years ago.
Let us consider the following program
def fib(n):
result = []
a, b = 0, 1
while b < n:
result.append(b)
a, b = b, a+b
c = result
print c
return result
f100 = fib(100)
print result
#print c
How can I access the variable 'c' from out side the function? Is it possible? I know
print result
will give the same, but i want to know is there any method to access 'c' outside the function?
You could declare c as global, although that's not generally a pattern you'd want to encourage. You'd do that like this:
c = None
def fib(n):
global c
result = []
a, b = 0, 1
while b < n:
result.append(b)
a, b = b, a+b
c = result
return result
f100 = fib(100)
print result
print c
You could also restructure your function as a class with a __call__ method which would let you expose internal values as attributes, such as:
class fibber(object):
def __init__(self):
self.c = None
def __call__(self, n):
result = []
a, b = 0, 1
while b < n:
result.append(b)
a, b = b, a+b
self.c = result
return result
fib = fibber()
f100 = fib(100)
print result
print fib.c
Local variables only exist in the context of the function they are defined in. That's what makes them local. So the whole variable c does not exist anymore once the function terminates and returns its result value.
You can of course save the value of that variable in a different one, e. g. a field of the function itself:
fib.c = c
Since the function itself will exist also after it terminated, so will its fields, and so will fib.c.
But I must stress that this is just a hack. Normally if you want to access a value outside of a function it is a good idea to make the variable holding that value not local.
You can declare c a global variable:
def fib(n):
global c
result = []
a, b = 0, 1
while b < n:
result.append(b)
a, b = b, a+b
c = result
print c
return result
result = fib(10)
print result
print c

call-by-reference function parameters

Given a function:
def A(a, b, c):
a *= 2
b *= 4
c *= 8
return a+b+c
How can I set the 'c' var to be called-by-reference, so if i call d = A(a,b,c), c will point to the same int object, and be updated from within the function?
You're getting into murky territory: you're talking about declaring global (or nonlocal) variables in functions, which should simply not be done. Functions are meant to do one thing, and do them without the consent of other values or functions affecting their state or output.
It's difficult to suggest a working example: are you alright with having copies of the variables left behind for later reference? You could expand this code to pass back a tuple, and reference the members of the tuple if needed, or the sum:
>>> def A(a, b, c):
return (a*2, b*4, c*8)
>>> d = A(2, 4, 8)
>>> sum(d)
84
>>> d[-1] #or whatever index you'd need...this may serve best as a constant
64
You can do this if c is a list:
c = [2]
def A(a, b, c):
a *= 2
b *= 4
c[0] *= 8
return a+b+c[0]
print c # gives [16]
You can't. Python cannot do that.
What you can do is pass a wrapper that has __imul__() defined and an embedded int, and the augmented assignment will result in the embedded attribute being mutated instead.
All calls in Python are "by reference". Integers are immutable in Python. You can't change them.
class C:
def __init__(self, c):
self.c = c
def __call__(self, a, b):
a *= 2
b *= 4
self.c *= 8
return a + b + self.c
Example
A = C(1)
print A(1, 1), A.c
print A(1, 1), A.c
Output
14 8
70 64

Categories