Global variable in Python changed by multiple functions - python

I want to create a global variable inside a class method and then change it by other functions. This is my code:
def funcA():
global x
print(x)
x = 2
a = funcB()
return x
def funcB():
global x
print(x)
x = 4
return 2
class A():
def method():
x = 0
return funcA()
A.method()
So I create variable x inside class method and then in all other methods which uses this variable I wrote global x. Unfortunately it doesn't work. What should I change? funcA should print 0, funcB should print 2 and the final results should be 4.

In general, use of global variables is frowned upon. If you see that a group of methods all need to manipulate the same variable it is often a sign that you actually want a class. You are on the right track trying to define the class, but unfortunately the syntax is a little more complicated
Here is one suggestion:
class A:
def method(self):
self.x = 0 # note use of self, to refer to the class instance
return self.funcA()
def funcA(self):
print(self.x)
self.x = 2
self.funcB()
def funcB(self):
print(self.x)
self.x = 4
a = A() # making an instance of A
a.method() # calling the method on the instance
print(a.x) # showing that x has become 4

create the variable globally. just add x = 0 at the starting of your code, it will work

x = 0
def funcA():
global x
print(x)
x = 2
a = funcB()
return x
def funcB():
global x
print(x)
x = 4
return 2
class A():
def method():
return funcA()
print(A.method())
It should work now, the problem was that you declared x inside class A, so it wasn't global.

Related

Changing a variable of one function from another function

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)

Python class variable accessed by multiple instances

I want to define a global variable which can be accessed (read and write) by all instances of the class. My current solution is shown in the example below. I don't like having a variable in the global namespace, but I was not able to put idx in class. How can I put idx in class and achieve the same?
# working
idx = 0
class test(object):
def add(self):
global idx
idx += 1
def print_x(self):
global idx
print(idx)
test1 = test()
test1.add()
test1.print_x()
test2 = test()
test2.add()
test2.print_x()
# Error
class test(object):
idx = 0
def add(self):
global idx
idx += 1
def print_x(self):
global idx
print(idx)
test1 = test()
test1.add()
test1.print_x()
test2 = test()
test2.add()
test2.print_x()
Traceback (most recent call last):
File "test.py", line 16, in <module>
test1.add()
File "test.py", line 9, in add
idx += 1
NameError: global name 'idx' is not defined
Your code fails because you tried to access a global variable idx without properly declaring it. You need to access your class variable.
class Test(object):
idx = 0
def add(self):
Test.idx += 1
obj = Test()
obj.add()
print(Test.idx)
obj = Test()
obj.add()
print(Test.idx)
Output:
1
2
Here's a hacky little way that doesn't need any global variables. It makes use of the fact that default arguments are only created once when __init__ is called for the first time and if the default arguments are mutable, then changing one of them will impact all future functions/instances of the same class.
We can create idx as a list since lists are mutable and then make sure we only modify that list in place. Doing so like this will ensure that all instances of your Test class point to the exact same idx list. Changing one changes them all, so long as you only do in-place modifications.
class Test:
def __init__(self, idx = [0]):
self.idx = idx
def add(self):
self.idx[0] += 1
a = Test()
b = Test()
a.add()
print(a.idx, b.idx)
# >> Prints [1], [1]
You can achieve this using a singleton pattern. Here is a small example with singleton:
class Singleton:
# Here will be the instance stored.
__instance = None
#staticmethod
def getInstance():
""" Static access method. """
if Singleton.__instance == None:
Singleton()
return Singleton.__instance
def add(self):
self.idx += 1
def __init__(self):
""" Virtually private constructor. """
if Singleton.__instance != None:
raise Exception("This class is a singleton!")
else:
Singleton.__instance = self
self.idx = 0
In [3]: main = Singleton()
In [4]: a = Singleton.getInstance()
In [5]: print(a.idx)
0
In [6]: a.add()
In [7]: print(a.idx)
1
In [8]: b = Singleton.getInstance()
In [9]: print(b.idx)
1
Ref: https://www.tutorialspoint.com/python_design_patterns/python_design_patterns_singleton.htm
There are some elegant Singleton examples on SO as well.
You have to define your variable in the class, outside of methods, and it shall not be a self variable. A self variable is unique to every instances.
In methods you have to use the class name for accessing the variable, otherwise the method will look at it as a private variable, and in most cases you will get an error, because it was not initialized before usage.
class MyClass:
my_public_variable = 0
__my_private_variable = 5
def inc(self):
MyClass.my_public_variable += 1
MyClass.__my_private_variable += 1
def show(self):
print(MyClass.my_public_variable)
print(MyClass.__my_private_variable)
obj1 = MyClass()
obj1.show()
obj2 = MyClass()
obj2.show()
obj1.inc()
obj2.show()
print(obj1.my_public_variable)
print(obj1.my_private_variable) # Invokes error
By running this code, the following will be printed out without the parenthesis:
0 (my_public_variable of obj1)
5 (my_private_variable of obj1)
0 (my_public_variable of obj2)
5 (my_private_variable of obj2)
1 (my_public_variable of obj2, incremented by obj1)
6 (my_private_variable of obj2, incremented by obj1)
1 (my_public_variable of obj1, it can be accessed outside of the class, since it is a public variable of the class)
Error (because, as its name suggests, my_private_variable is a private variable of the class)

How to access class variable in method when class and class method have same variable with name also?

I am unable to access class variable in method of same class and my method also having same name of class variable
class x(object):
x = 10 # class variable
def method1(self,v1):
x = v1 # method variable
# here I want to access class variable
This code will help you understand the difference between class variable, instance variable and local variable.
class Test:
x = 10 //class variable or static variable; shared by all objects
def __init__(self):
self.x = 20 //instance variable; different value for each object
def func(self, x): //method variable
print Test.x
print self.x
print x
Output:
102030
Test.x prints the static varible. To use instance variable you have to use self.instance_variable and you can directly use the local variable by its name inside the method.
You need to do as follows!
As Barmar mentioned, it isnt a good practice to use the same name for class and class variable!
>>> class x():
... def method(self, v1):
... self.x = v1
... print self.x
...
>>> y = x()
>>> y.method(5)
5
>>> y.x
5

How do I reference the variable declared under a class in Python?

I am relatively new to Python and I am using Python 2.7.x
I have a question regarding namespaces in Python:
class Team():
x = 2
def p(self):
print x
a = Team()
a.p()
When I run the code, it says global x is not defined. Shouldn't x belong to the Team object? My goal is to create a Team class where x has a default value of 2.
In Java it would be something like:
class Team()
{
int x = 2;
}
a = new Team();
If you want an instance attribute and a default value of 2 :
class Team(object): # use object for new style classes
def __init__(self, x=2):
self.x = x # use self to refer to the instance
def p(self):
print self.x # self.x
a = Team()
a.p()
2
b = Team(4) # give b a different value for x
b.p()
4
Difference between class vs instance attributes
new vs old style classes
If you want make x as class variable, just try this way:
class Team(object):
x = 2
def __init__(self):
pass
print Team.x
Team.x = 3
print Team.x
You don't need to instance to get the value and you can change it as you want.
If you want to make the num as instance property, you have to use self(like this in Java):
class Team(object):
def __init__(self, num):
self.num = num
def get_num(self):
return self.num
def set_num(self, change_num):
self.num = change_num
t1 = Team(2)
print t1.get_num()
t1.set_num(3)
print t1.get_num()

Python - why use "self" in a class?

How do these 2 classes differ?
class A():
x=3
class B():
def __init__(self):
self.x=3
Is there any significant difference?
A.x is a class variable.
B's self.x is an instance variable.
i.e. A's x is shared between instances.
It would be easier to demonstrate the difference with something that can be modified like a list:
#!/usr/bin/env python
class A:
x = []
def add(self):
self.x.append(1)
class B:
def __init__(self):
self.x = []
def add(self):
self.x.append(1)
x = A()
y = A()
x.add()
y.add()
print("A's x:", x.x)
x = B()
y = B()
x.add()
y.add()
print("B's x:", x.x)
Output
A's x: [1, 1]
B's x: [1]
Just as a side note: self is actually just a randomly chosen word, that everyone uses, but you could also use this, foo, or myself or anything else you want, it's just the first parameter of every non static method for a class. This means that the word self is not a language construct but just a name:
>>> class A:
... def __init__(s):
... s.bla = 2
...
>>>
>>> a = A()
>>> a.bla
2
A.x is a class variable, and will be shared across all instances of A, unless specifically overridden within an instance.
B.x is an instance variable, and each instance of B has its own version of it.
I hope the following Python example can clarify:
>>> class Foo():
... i = 3
... def bar(self):
... print 'Foo.i is', Foo.i
... print 'self.i is', self.i
...
>>> f = Foo() # Create an instance of the Foo class
>>> f.bar()
Foo.i is 3
self.i is 3
>>> Foo.i = 5 # Change the global value of Foo.i over all instances
>>> f.bar()
Foo.i is 5
self.i is 5
>>> f.i = 3 # Override this instance's definition of i
>>> f.bar()
Foo.i is 5
self.i is 3
I used to explain it with this example
# By TMOTTM
class Machine:
# Class Variable counts how many machines have been created.
# The value is the same for all objects of this class.
counter = 0
def __init__(self):
# Notice: no 'self'.
Machine.counter += 1
# Instance variable.
# Different for every object of the class.
self.id = Machine.counter
if __name__ == '__main__':
machine1 = Machine()
machine2 = Machine()
machine3 = Machine()
#The value is different for all objects.
print 'machine1.id', machine1.id
print 'machine2.id', machine2.id
print 'machine3.id', machine3.id
#The value is the same for all objects.
print 'machine1.counter', machine1.counter
print 'machine2.counter', machine2.counter
print 'machine3.counter', machine3.counter
The output then will by
machine1.id 1
machine2.id 2
machine3.id 3
machine1.counter 3
machine2.counter 3
machine3.counter 3
I've just started learning Python and this confused me as well for some time. Trying to figure out how it all works in general I came up with this very simple piece of code:
# Create a class with a variable inside and an instance of that class
class One:
color = 'green'
obj2 = One()
# Here we create a global variable(outside a class suite).
color = 'blue'
# Create a second class and a local variable inside this class.
class Two:
color = "red"
# Define 3 methods. The only difference between them is the "color" part.
def out(self):
print(self.color + '!')
def out2(self):
print(color + '!')
def out3(self):
print(obj2.color + '!')
# Create an object of the class One
obj = Two()
When we call out() we get:
>>> obj.out()
red!
When we call out2():
>>> obj.out2()
blue!
When we call out3():
>>> obj.out3()
green!
So, in the first method self specifies that Python should use the variable(attribute), that "belongs" to the class object we created, not a global one(outside the class). So it uses color = "red". In the method Python implicitly substitutes self for the name of an object we created(obj). self.color means "I am getting color="red" from the obj"
In the second method there is no self to specify the object where the color should be taken from, so it gets the global one color = 'blue'.
In the third method instead of self we used obj2 - a name of another object to get color from. It gets color = 'green'.

Categories

Resources