Changing a variable of one function from another function - python

Is there a way to change a variable inside function A from function B when function A called function B
For example:
def a():
flag = False
b()
print(flag)
def b():
flag = True
I would like flag == True
another example:
def a():
list = [1,2,3]
b():
return list
def b():
list.append(4)

The flag variable is locally scoped to function A and B. This does not mean that they are the same variable. They're completely different from each other, occupying a completely different address space all together.
If you would like function B to change the value of your flag variable in function A, you can simply have function B return the value.
def b():
flag = True
return flag
Another method is to use pass by reference, which allows you to alter the value of the variable in that memory address space. This only works for mutable objects. In this case, a boolean is immutable so a pass by reference isn't possible here.

you need to pass it either as a parameter to the function or create a global variable (usually considered to be bad style)
flag = False
def a():
b()
print(flag)
def b():
global flag
flag = True
a() # True

I would consider creating a class for that. In this way instead of following a global variable, you just need to track the object:
class flagChangerClass():
def __init__(self):
self.flag = False
def a(self):
self.b()
print(self.flag)
def b(self):
flag = True
That way you can call it after initializing the object:
flagChanger = flagChangerClass() #Equivalent to flag = False
flagChanger.a() # Changes flag by calling function b in class
If you want with the list:
class listChangerClass():
def __init__(self):
self.internalList = [1,2,3]
def a(self):
self.b()
print(self.internalList )
def b(self):
self.internalList.append(4)
listChanger = listChangerClass()
listChanger.a()
print(listChanger.internalList)

Related

How to access variables created in __init__ in another def in the same instance of a class?

Goal: Being able to access a in play.
Note: I need to save information via variables in the same instance of the class because play will be called multiple times.
Code:
class something():
def __init__(self):
a = 2
def play(self, b):
return True if a == b else False
test = something()
print(test.play(1))
Expectations: It should print False because 2 != 1, but I get this error instead:
UnboundLocalError: local variable 'a' referenced before assignment
I've tried:
Getting rid of __init__ and just putting the int outside a def.
Setting up the int before __init__ and just accessing it in __init__.
Note: I can't pass arguments to __init__ while making a new instance of the class, this is for an exercise, which can be found here, and I don't control the creation of a new instance.
class something():
def __init__(self):
self.a = 2
def play(self, b):
return True if self.a == b else False
test = something()
print(test.play(1))
In the __init__ you have to use self.variable and same can be used in other functions too of same class.

See function stop from locating defined class in Python

I'd like to define a class inside a function (for testing purpose) and put a value into
a function variable:
def foo():
myvar = None
class myclass:
def run(self):
myvar = 5
mm = myclass()
mm.run()
print(myvar)
The above prints None
Is there any way other than global to make the myvar variable accessible from the class? The correct answer would print 5
It's not possible to assign a value to a variable outside the current scope without global. If you need to persist the value within the class you can define class variables instead. Example:
def foo():
class Class:
var_to_change = None
def run (self):
self.var_to_change = 5
print (Class.var_to_change)
instance = Class()
instance.run()
print (Class.var_to_change)
I haven't tested the above code but it should work in theory.

How to detect changes of a list whithin a Python class, or why does "setter" not trigger

I would like to have a list in a Python class. Whenever an element in the list is changed I need to run some logic. I'm pretty new to classes in python and my approach with the setter might be pretty naive. This is what makes intuitive sense to me:
class test():
def __init__(self):
self._R = [False]*16
#property
def R(self):
return self._R
#R.setter
def R(self,a):
print('Why do I not get reached?')
self._R = a
W = test()
W.R[0] = True
But the setter never gets triggered. If you could give me a notch in the right direction, I would be very great full.
You can create a new List-like class that takes a callback function and executes it whenever the list is changed:
class CallbackList: # PEP-8 style suggests UpperCase class names
def __init__(self, callback=None):
self._list = [False]
self._callback = callback # Python functions are first-class objects just like ints, strings, etc, so this is completely legal
def __setitem__(self, index, value):
self._list[index] = value
if self._callback:
self._callback() # Executes the callback function whenever a value is set
def __getitem__(self, index):
return self._list[index]
class Test:
def __init__(self):
self.callback_list = CallbackList(callback=self.foo)
def foo(self):
print("You changed the list!")
W = Test()
W.callback_list[0] = True # This prints "You changed the list!"
Note that this still won't catch every possible change. For example:
W = Test()
some_list = [1, 2, 3]
W.callback_list[0] = some_list # This triggers the callback function
print(W.callback_list[0]) # [1, 2, 3]
some_list.append(4) # This does NOT trigger the callback function!
print(W.callback_list[0]) # [1, 2, 3, 4] !
I tried to write code according to #user2357112supportsMonica comments:
class test():
def __init__(self):
self.A = 1
def foo(self):
print(self.A)
class R_Class():
def __init__(self):
self._R = [False]*16
def __setitem__(self,index,value):
self._R[index] = value
test.foo() #Here I need to call foo somehow
def __getitem__(self,index):
return self._R[index]
R = R_Class()
W = test()
W.R[0] = True
But this approach leads to another problem, is there a way to properly call the foo function from within the sub class?

Is every function in the class with `self` an instance variable even if it just does something unrelated to the specific instance?

So would this be an instance variable or a class variable?
def f(self): # is this instance.f an instance variable?
return 'hello world'
the instance.f() command returns the same thing for all instances so is this unique to the instances or the class?
Even if it does something unrelated to the specific instance, it always receives a different instance as the self argument. It might be better to use a static method instead:
#staticmethod
def f():
return 'hello world'
Now it is unique:
class C:
def f(self):
return 'hello world'
a = C()
b = C()
print(a.f == b.f) # False
class C:
#staticmethod
def f():
return 'hello world'
a = C()
b = C()
print(a.f == b.f) # True

How to print a variable from a derived class?

I know there are similar questions on this topics but none of them seem to apply to my case
Why would the following code print None and not True?
Thanks
class A(object):
flag = None
#classmethod
def set_flag(cls):
cls.flag = True
class B(A):
#classmethod
def print_super_flag(cls):
print cls.__bases__[0].flag # This prints None
print super(B, cls).flag # This also
if __name__ == "__main__":
b = B()
b.set_flag()
b.print_super_flag()
This call:
b.set_flag()
You defined set_flag as:
#classmethod
def set_flag(cls):
cls.flag = True
So when b calls set_flag, cls is B - so it sets B.flag, not A.flag. Then when you go to print A.flag, it is None because you never touched it. So your issue is not at all in print_super_flag - you access A.flag correctly there. Twice.
If instead you defined set_flag as:
class A(object):
flag = None
#classmethod
def set_flag(cls):
A.flag = True
Your code prints out True (twice), because set_flag now sets A.flag in derived classes. Of course at this point your method being a classmethod is moot, but that's a function of how you expect the method to perform; when you call a classmethod from a derived class, cls is that derived class, not the parent class.
Try this slightly extended version to see what's going on:
class A(object):
flag = None
#classmethod
def set_flag(cls):
cls.flag = True
class B(A):
#classmethod
def print_super_flag(cls):
print cls.__bases__[0].flag # This prints None
print super(B, cls).flag # This also
if __name__ == "__main__":
b = B()
b.set_flag()
print b.flag
b2 = B()
print b2.flag
a = A()
print a.flag
Prints:
True # because you set b.flag
True # because b.flag and b2.flag refer to the same class variable, B.flag
None # because B.flag and A.flag are NOT the same class variable
Basically, the child class (B) has its own copy of the flag class variable, rather than sharing it with the parent class (A).
More details here, assuming you're using Python 2.7-ish.
If you only want there to only one flag attribute that's part of the base class, you need to change the set_flag() method to:
class A(object):
flag = None
#classmethod
def set_flag(cls):
A.flag = True
Since the revised method doesn't reference its cls argument, you could just make it staticmethod and remove the argument, although that's not extremely important. Regardless, by hardcoding the base class, you ensure which flag attribute is being set, otherwise another flag attribute will be created as part of cls argument, which is the class the call was made through.
Since only one class attribute exists, its value will be printed.

Categories

Resources