variable reference and manipulation from object to function in python - python

I have wrote following code in python
class check(object):
def __init__(self):
self.a = [1,2,3,4]
self.b = 5
appending(self.a, self.b)
print "a", self.a
print "b", self.b
def appending(a,b):
a.append(5)
b +=1
If now I run check() function, I got output as following:
a [1,2,3,4,5] [1,2,3,4,5]
b 5 5
So, I have following question
Why it is that list(a) is got updated but not int(b)?
It is related that I am modifying a but i am creating new object when I add 1 in b, in short, it is difference due to immutable or mutable data types.
I have define self.a and self.b in object, i have define a,b in function, then why I can write print a and print b in object, get same output as self.a and self.b

self.b is a name for an integer 5. The integer is an immutable object.
When you appear to mutate b you actually create a new object 6 and assign b as a name for it. This in no way affects the object 5 which self.b is a name for.

Since a is a list, it's passed by reference to the method and any changed done to it within the method, will be done directly to the a.
Variable b is an integer, therefore it's passed by value and a copy of the variable is created to be used within the method. Any change will be visible only within the body of the method, but not to the "outside world".

Related

Why is numeric type deleted and list type not, when they are attributes to a class instance (which gets deleted)?

In the below code sample I would expect both a and b to be deleted at the end of each loop.
What happens is that a is deleted but not b. Why is that? And how can I make sure that b is also deleted at the end of each loop?
class bag:
a = 5
b = []
def funcie(self):
self.a = self.a + 1
self.b.append(1)
for i in range(5):
inst = bag()
inst.funcie()
print(inst.a)
print(inst.b)
# del inst
output:
6
[1]
6
[1, 1]
6
[1, 1, 1]
6
[1, 1, 1, 1]
6
[1, 1, 1, 1, 1]
EDIT: So this post explains why the b list keeps growing in each loop i.e. I should have declared the b list in the __init(self)__ function.
However it doesn't explain why the a variable gets overwritten at the end of each loop whilst the b variable doesn't.
bag.a (a class attribute) is not being overridden, it's being shadowed by the instance's a (an instance attribute) for inst specifically.
Python's general rule is that reading will read from outer/shadowed scopes if there is no inner/shadowing scope hiding it. An inner/shadowing scope is created by assignment, not merely mutation (which is just reading from the variable then asking it to mutate itself). There are some subtle distinctions between how scopes and attributes work, so I'm going to focus on attributes only (since that's what you asked about).
When you do self.a = self.a + 1 on a new instance of bag, the self.a you read comes from the class attribute, but on writing to self.a, you create a new shadowing instance attribute. The class attribute (bag.a == 5) still exists, and is unmodified, but from the instance's point of view, it only sees the instance attribute (inst.a == 6). If you added print(bag.a), you'd see if never changed.
By contrast, self.b.append(1) reads the class attribute and asks it to modify itself in place, which changes object bound to the class attribute itself.
If you want to modify a class attribute without creating an instance attribute, you have to operate on the class itself. For example, you could change:
self.a = self.a + 1
to:
type(self).a = self.a + 1 # Or type(self).a = type(self).a + 1
or more simply use += to avoid repeating more complex stuff:
type(self).a += 1
Numbers differ from the list in that Python uses their value and stores the result of computations in a new place. So the result of a = a+1 is stored in a different location in memory each time. Lists remain in the same memory location and are updated in place. The following code:
class bag:
a = 5
b = []
def funcie(self):
self.a += 1
self.b.append(1)
inst = bag()
print("bag memory ids: ", id(bag.a), id(bag.b))
print("inst memory ids: ", id(inst.a), id(inst.b))
inst.funcie()
print("ids after 1x funcie:", id(inst.a), id(inst.b))
inst.funcie()
print("ids after 2x funcie:", id(inst.a), id(inst.b))
has this output, where you see the id of inst.a changing, while inst.b retains the same id:
bag memory ids: 9789120 139707042123328
inst memory ids: 9789120 139707042123328
ids after 1x funcie: 9789152 139707042123328
ids after 2x funcie: 9789184 139707042123328
So the updated value of a is stored in a different location, without altering the original value.

the answer variable is not being updated in max depth of binary tree question [duplicate]

Consider this example:
def A():
b = 1
def B():
# I can access 'b' from here.
print(b)
# But can i modify 'b' here?
B()
A()
For the code in the B function, the variable b is in a non-global, enclosing (outer) scope. How can I modify b from within B? I get an UnboundLocalError if I try it directly, and using global does not fix the problem since b is not global.
Python implements lexical, not dynamic scope - like almost all modern languages. The techniques here will not allow access to the caller's variables - unless the caller also happens to be an enclosing function - because the caller is not in scope. For more on this problem, see How can I access variables from the caller, even if it isn't an enclosing scope (i.e., implement dynamic scoping)?.
On Python 3, use the nonlocal keyword:
The nonlocal statement causes the listed identifiers to refer to previously bound variables in the nearest enclosing scope excluding globals. This is important because the default behavior for binding is to search the local namespace first. The statement allows encapsulated code to rebind variables outside of the local scope besides the global (module) scope.
def foo():
a = 1
def bar():
nonlocal a
a = 2
bar()
print(a) # Output: 2
On Python 2, use a mutable object (like a list, or dict) and mutate the value instead of reassigning a variable:
def foo():
a = []
def bar():
a.append(1)
bar()
bar()
print a
foo()
Outputs:
[1, 1]
You can use an empty class to hold a temporary scope. It's like the mutable but a bit prettier.
def outer_fn():
class FnScope:
b = 5
c = 6
def inner_fn():
FnScope.b += 1
FnScope.c += FnScope.b
inner_fn()
inner_fn()
inner_fn()
This yields the following interactive output:
>>> outer_fn()
8 27
>>> fs = FnScope()
NameError: name 'FnScope' is not defined
I'm a little new to Python, but I've read a bit about this. I believe the best you're going to get is similar to the Java work-around, which is to wrap your outer variable in a list.
def A():
b = [1]
def B():
b[0] = 2
B()
print(b[0])
# The output is '2'
Edit: I guess this was probably true before Python 3. Looks like nonlocal is your answer.
No you cannot, at least in this way.
Because the "set operation" will create a new name in the current scope, which covers the outer one.
I don't know if there is an attribute of a function that gives the __dict__ of the outer space of the function when this outer space isn't the global space == the module, which is the case when the function is a nested function, in Python 3.
But in Python 2, as far as I know, there isn't such an attribute.
So the only possibilities to do what you want is:
1) using a mutable object, as said by others
2)
def A() :
b = 1
print 'b before B() ==', b
def B() :
b = 10
print 'b ==', b
return b
b = B()
print 'b after B() ==', b
A()
result
b before B() == 1
b == 10
b after B() == 10
.
Nota
The solution of Cédric Julien has a drawback:
def A() :
global b # N1
b = 1
print ' b in function B before executing C() :', b
def B() :
global b # N2
print ' b in function B before assigning b = 2 :', b
b = 2
print ' b in function B after assigning b = 2 :', b
B()
print ' b in function A , after execution of B()', b
b = 450
print 'global b , before execution of A() :', b
A()
print 'global b , after execution of A() :', b
result
global b , before execution of A() : 450
b in function B before executing B() : 1
b in function B before assigning b = 2 : 1
b in function B after assigning b = 2 : 2
b in function A , after execution of B() 2
global b , after execution of A() : 2
The global b after execution of A() has been modified and it may be not whished so
That's the case only if there is an object with identifier b in the global namespace
The short answer that will just work automagically
I created a python library for solving this specific problem. It is released under the unlisence so use it however you wish. You can install it with pip install seapie or check out the home page here https://github.com/hirsimaki-markus/SEAPIE
user#pc:home$ pip install seapie
from seapie import Seapie as seapie
def A():
b = 1
def B():
seapie(1, "b=2")
print(b)
B()
A()
outputs
2
the arguments have following meaning:
The first argument is execution scope. 0 would mean local B(), 1 means parent A() and 2 would mean grandparent <module> aka global
The second argument is a string or code object you want to execute in the given scope
You can also call it without arguments for interactive shell inside your program
The long answer
This is more complicated. Seapie works by editing the frames in call stack using CPython api. CPython is the de facto standard so most people don't have to worry about it.
The magic words you are probably most likely interesed in if you are reading this are the following:
frame = sys._getframe(1) # 1 stands for previous frame
parent_locals = frame.f_locals # true dictionary of parent locals
parent_globals = frame.f_globals # true dictionary of parent globals
exec(codeblock, parent_globals, parent_locals)
ctypes.pythonapi.PyFrame_LocalsToFast(ctypes.py_object(frame),ctypes.c_int(1))
# the magic value 1 stands for ability to introduce new variables. 0 for update-only
The latter will force updates to pass into local scope. local scopes are however optimized differently than global scope so intoducing new objects has some problems when you try to call them directly if they are not initialized in any way. I will copy few ways to circumvent these problems from the github page
Assingn, import and define your objects beforehand
Assingn placeholder to your objects beforehand
Reassign object to itself in main program to update symbol table: x = locals()["x"]
Use exec() in main program instead of directly calling to avoid optimization. Instead of calling x do: exec("x")
If you are feeling that using exec() is not something you want to go with you can
emulate the behaviour by updating the the true local dictionary (not the one returned by locals()). I will copy an example from https://faster-cpython.readthedocs.io/mutable.html
import sys
import ctypes
def hack():
# Get the frame object of the caller
frame = sys._getframe(1)
frame.f_locals['x'] = "hack!"
# Force an update of locals array from locals dict
ctypes.pythonapi.PyFrame_LocalsToFast(ctypes.py_object(frame),
ctypes.c_int(0))
def func():
x = 1
hack()
print(x)
func()
Output:
hack!
I don't think you should want to do this. Functions that can alter things in their enclosing context are dangerous, as that context may be written without the knowledge of the function.
You could make it explicit, either by making B a public method and C a private method in a class (the best way probably); or by using a mutable type such as a list and passing it explicitly to C:
def A():
x = [0]
def B(var):
var[0] = 1
B(x)
print x
A()
For anyone looking at this much later on a safer but heavier workaround is. Without a need to pass variables as parameters.
def outer():
a = [1]
def inner(a=a):
a[0] += 1
inner()
return a[0]
You can, but you'll have to use the global statment (not a really good solution as always when using global variables, but it works):
def A():
global b
b = 1
def B():
global b
print( b )
b = 2
B()
A()

Global variable getting error "NameError: name 'variable' is not defined" [duplicate]

Consider this example:
def A():
b = 1
def B():
# I can access 'b' from here.
print(b)
# But can i modify 'b' here?
B()
A()
For the code in the B function, the variable b is in a non-global, enclosing (outer) scope. How can I modify b from within B? I get an UnboundLocalError if I try it directly, and using global does not fix the problem since b is not global.
Python implements lexical, not dynamic scope - like almost all modern languages. The techniques here will not allow access to the caller's variables - unless the caller also happens to be an enclosing function - because the caller is not in scope. For more on this problem, see How can I access variables from the caller, even if it isn't an enclosing scope (i.e., implement dynamic scoping)?.
On Python 3, use the nonlocal keyword:
The nonlocal statement causes the listed identifiers to refer to previously bound variables in the nearest enclosing scope excluding globals. This is important because the default behavior for binding is to search the local namespace first. The statement allows encapsulated code to rebind variables outside of the local scope besides the global (module) scope.
def foo():
a = 1
def bar():
nonlocal a
a = 2
bar()
print(a) # Output: 2
On Python 2, use a mutable object (like a list, or dict) and mutate the value instead of reassigning a variable:
def foo():
a = []
def bar():
a.append(1)
bar()
bar()
print a
foo()
Outputs:
[1, 1]
You can use an empty class to hold a temporary scope. It's like the mutable but a bit prettier.
def outer_fn():
class FnScope:
b = 5
c = 6
def inner_fn():
FnScope.b += 1
FnScope.c += FnScope.b
inner_fn()
inner_fn()
inner_fn()
This yields the following interactive output:
>>> outer_fn()
8 27
>>> fs = FnScope()
NameError: name 'FnScope' is not defined
I'm a little new to Python, but I've read a bit about this. I believe the best you're going to get is similar to the Java work-around, which is to wrap your outer variable in a list.
def A():
b = [1]
def B():
b[0] = 2
B()
print(b[0])
# The output is '2'
Edit: I guess this was probably true before Python 3. Looks like nonlocal is your answer.
No you cannot, at least in this way.
Because the "set operation" will create a new name in the current scope, which covers the outer one.
I don't know if there is an attribute of a function that gives the __dict__ of the outer space of the function when this outer space isn't the global space == the module, which is the case when the function is a nested function, in Python 3.
But in Python 2, as far as I know, there isn't such an attribute.
So the only possibilities to do what you want is:
1) using a mutable object, as said by others
2)
def A() :
b = 1
print 'b before B() ==', b
def B() :
b = 10
print 'b ==', b
return b
b = B()
print 'b after B() ==', b
A()
result
b before B() == 1
b == 10
b after B() == 10
.
Nota
The solution of Cédric Julien has a drawback:
def A() :
global b # N1
b = 1
print ' b in function B before executing C() :', b
def B() :
global b # N2
print ' b in function B before assigning b = 2 :', b
b = 2
print ' b in function B after assigning b = 2 :', b
B()
print ' b in function A , after execution of B()', b
b = 450
print 'global b , before execution of A() :', b
A()
print 'global b , after execution of A() :', b
result
global b , before execution of A() : 450
b in function B before executing B() : 1
b in function B before assigning b = 2 : 1
b in function B after assigning b = 2 : 2
b in function A , after execution of B() 2
global b , after execution of A() : 2
The global b after execution of A() has been modified and it may be not whished so
That's the case only if there is an object with identifier b in the global namespace
The short answer that will just work automagically
I created a python library for solving this specific problem. It is released under the unlisence so use it however you wish. You can install it with pip install seapie or check out the home page here https://github.com/hirsimaki-markus/SEAPIE
user#pc:home$ pip install seapie
from seapie import Seapie as seapie
def A():
b = 1
def B():
seapie(1, "b=2")
print(b)
B()
A()
outputs
2
the arguments have following meaning:
The first argument is execution scope. 0 would mean local B(), 1 means parent A() and 2 would mean grandparent <module> aka global
The second argument is a string or code object you want to execute in the given scope
You can also call it without arguments for interactive shell inside your program
The long answer
This is more complicated. Seapie works by editing the frames in call stack using CPython api. CPython is the de facto standard so most people don't have to worry about it.
The magic words you are probably most likely interesed in if you are reading this are the following:
frame = sys._getframe(1) # 1 stands for previous frame
parent_locals = frame.f_locals # true dictionary of parent locals
parent_globals = frame.f_globals # true dictionary of parent globals
exec(codeblock, parent_globals, parent_locals)
ctypes.pythonapi.PyFrame_LocalsToFast(ctypes.py_object(frame),ctypes.c_int(1))
# the magic value 1 stands for ability to introduce new variables. 0 for update-only
The latter will force updates to pass into local scope. local scopes are however optimized differently than global scope so intoducing new objects has some problems when you try to call them directly if they are not initialized in any way. I will copy few ways to circumvent these problems from the github page
Assingn, import and define your objects beforehand
Assingn placeholder to your objects beforehand
Reassign object to itself in main program to update symbol table: x = locals()["x"]
Use exec() in main program instead of directly calling to avoid optimization. Instead of calling x do: exec("x")
If you are feeling that using exec() is not something you want to go with you can
emulate the behaviour by updating the the true local dictionary (not the one returned by locals()). I will copy an example from https://faster-cpython.readthedocs.io/mutable.html
import sys
import ctypes
def hack():
# Get the frame object of the caller
frame = sys._getframe(1)
frame.f_locals['x'] = "hack!"
# Force an update of locals array from locals dict
ctypes.pythonapi.PyFrame_LocalsToFast(ctypes.py_object(frame),
ctypes.c_int(0))
def func():
x = 1
hack()
print(x)
func()
Output:
hack!
I don't think you should want to do this. Functions that can alter things in their enclosing context are dangerous, as that context may be written without the knowledge of the function.
You could make it explicit, either by making B a public method and C a private method in a class (the best way probably); or by using a mutable type such as a list and passing it explicitly to C:
def A():
x = [0]
def B(var):
var[0] = 1
B(x)
print x
A()
For anyone looking at this much later on a safer but heavier workaround is. Without a need to pass variables as parameters.
def outer():
a = [1]
def inner(a=a):
a[0] += 1
inner()
return a[0]
You can, but you'll have to use the global statment (not a really good solution as always when using global variables, but it works):
def A():
global b
b = 1
def B():
global b
print( b )
b = 2
B()
A()

Class variable Vs. Instance variable in python for int value

I am new to python and i am not sure how this is working. Code is as below:
class test():
d=0
def __init__(self):
self.d=self.d+1;
D=test()
print D.d
D1=test()
print D1.d
D2=test()
print D2.d
Output is
1,1,1 # This should not be
Now using this :
class test():
d=[]
def __init__(self):
self.d.apend("1");
D=test()
print D.d
D1=test()
print D1.d
D2=test()
print D2.d
Result is (This should be)
['1']
['1', '1']
['1', '1', '1']
So i am not sure why integer value is not being treated as class variable while list is being treated.
In the first example,
self.d = self.d + 1
rebinds self.d, making it independent of test.d.
In the second example,
self.d.append("1")
modifies test.d.
To see that for yourself, print id(self.d) at the end of both constructors.
If you modified the second example to match the first:
self.d = self.d + ["1"]
you'd see that the behaviour would also change to match.
If you want to modify a class variable, do:
class test(object):
d=0
def __init__(self):
type(self).d=self.d+1;
D=test()
print D.d
D1=test()
print D1.d
D2=test()
print D2.d
You don't need the type on the right hand side of the assignment, because this way you never create an instance variable d. Note that new-style classes are necessary to this.
type is a function (actually a callable - it is also a class; but don't worry about that for now) which returns the class of its argument. So, type(self) returns the class of self. Classes are first class objects in Python.
Demo here: http://ideone.com/JdNpiV
Update: An alternative would be to use a classmethod.
To address a class variable use class_name.variable_name, giving :
class test(object):
d=0
def __init__(self):
test.d = test.d + 1;
NPE's answer tells you what is going wrong with your code. However, I'm not sure that it really tells you how to solve the issue properly.
Here's what I think you want, if each test instance should have a different d value in an instance variable:
class test(object): # new style class, since we inherit from "object"
_d = 0 # this is a class variable, which I've named _d to avoid confusion
def __init__(self):
self.d = test._d # assign current value of class variable to an instance variable
test._d += 1 # increment the class variable
Now, you can create multiple instances and each one will get a unique value for d:
>>> D0 = test()
>>> D1 = test()
>>> D2 = test()
>>> print D0.d
0
>>> print D1.d
1
>>> print D2.d
2

What is happening in this Python program?

I'd like to know what is getting assigned to what in line 8.
# Iterators
class Fibs:
def __init__(self):
self.a = 0
self.b = 1
def next(self):
self.a, self.b = self.b, self.a+self.b # <--- here
return self.a
def __iter__(self):
return self
fibs = Fibs()
for f in fibs:
if f > 1000:
print f
break
The rest of the program I really don't need much explanation. I'm not sure what's getting assigned to what.
It's a multiple assignment roughly equivalent to this:
tmp = self.a
self.a = self.b
self.b = tmp + self.b
Or this pseudo-code:
a' = b
b' = a + b
As you can see the multiple assignment is much more concise than separate assignments and more closely resembles the pseudo-code example.
Almost that example is given in the Python documentation as an example of calculating Fibonacci numbers. One of the advantages of the multiple assignment is that the variables on the right hand side are evaluated before any of the assignments take place, saving the need for the temporary variable in this case.
It's a pair assignment, a shorthand of
t = self.a
self.a = self.b
self.b = t+self.b
just to use an one-liner instead that two assignments.. to be precise i think that the left operand of the assignment is considered a tuple of two elements, so you are like assigning to tuple (self.a, self,b) the value (self.b, self.a+self.b) which does the same thing as the three separate assignments written before without the need of a temporary variable. This because, while without using tuple the assignments are executed sequentially, in your example they are resolved at the same time, preserving the value of self.a in second assignment.
As stated in documentation:
Assignment of an object to a target list is recursively defined as follows.
If the target list is a single target: The object is assigned to that target.
If the target list is a comma-separated list of targets (your case): The object must be an iterable with the same number of items as there are targets in the target list, and the items are assigned, from left to right, to the corresponding targets. (This rule is relaxed as of Python 1.5; in earlier versions, the object had to be a tuple. Since strings are sequences, an assignment like a, b = "xy" is now legal as long as the string has the right length.)
Without looking at the surrounding code, I'd say it's the heart of an algorithm for computing Fibonacci numbers.
It translates to the equivalent of:
a = b
b = a + b
...thereby computing the next number(s) in the sequence.
If you look at a sequence of numbers like
1 1 2 3 5 8 13 21 ...
and you let a and b be the last two numbers, then afterwards you'll have the next number in b and the former last number (b) in a.
The reason to use that strange notation is so as to accomplish both assignments at the same time. If they were done sequentially as in the 2 lines above, the value of a would be clobbered in the first line and you'd just be doubling b in the 2nd line.
Be aware that a paired assignment is not a "special feature" of Python. If you know a bit about Python, it's something you already know about but you may not know you know. When you put the following into the python console:
>>> 'a', 'b'
What you get in return is:
('a', 'b')
In other words, a tuple. In your example,
self.a, self.b = self.b, self.a+self.b
what you're really doing is:
(self.a, self.b) = (self.b, self.a+self.b)
Create a tuple that contains the value of self.b and the value of self.a+self.b. (The tuple on the right.)
Create a tuple that contains self.a and self.b. (The left-hand tuple.)
In order to create that left-hand tuple, create a new instance of self.a and self.b for that new tuple. Their old values don't matter anymore: they're in the temporary right-hand tuple.
Assign value 0 of the left tuple variable to value 0 of the right tuple.
Assign value 1 of the left tuple variable to value 1 of the right tuple.
Now that both variables of the left tuple are assigned, delete both tuples. The new variables remain with their new values.
So, for example, you can do:
>>> a, b = 1, 2
>>> a, b
(1, 2)
>>> a, b = b, a
>>> a, b
(2, 1)
There are still temporary variables involved under the hood, but you, the programmer, don't have to deal with them.

Categories