I have a program like :
class ABC:
q = {}
def update:
self.state = (xx,xx)
global q
if self.state in q:
// do something
I am getting the error :
"NameError: global name 'q' is not defined"
Im new to python and need some help.
You can move q outside of the class:
q = {}
class ABC:
def update:
self.state = (xx,xx)
global q
if self.state in q:
# do something
pass
or you can reference q as a class variable:
class ABC:
q = {}
def update:
self.state = (xx,xx)
if self.state in ABC.q:
# do something
pass
q isn't being declared as a global variable here - it's being declared as a class variable of class ABC.
If you want q to be global, you should define it before you start declaring the class.
Related
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.
I am trying to call a class variable within a staticmethod, but when I called I am getting an error "hello" is not defined. any advise ?
class hello:
random1 = []
#staticmethod
def sub(x):
hello.random1.append(x -1)
sub.__func__(2)
if __name__ == "__main__":
print(hello.random1)
hello doesn't exist as a global name until you dedent out of the class definition (at which point the class is created and assigned to the global name hello). Change the code to:
class hello:
random1 = []
#staticmethod
def sub(x):
hello.random1.append(x -1)
hello.sub(2)
so sub is invoked after hello exists, and it will work.
I am new to python.
Base class/python file(Base.py).
SESSION_ID = ""
def m1():
print "SESSION_ID in base: ",SESSION_ID
Derived class(Derived.py)
from Base import *
class Derived():
def m2(self):
global SESSION_ID
SESSION_ID = 10
print "SESSION_ID in derived: ", SESSION_ID
def main():
c2 = Derived()
c2.m2()
m1()
if __name__ == "__main__":
main()
When I execute Derived.py file below is the output:
SESSION_ID in derived: 10
SESSION_ID in base:
I want the value which is set in m2() to be reflected in m1(). So the expected output is:
SESSION_ID in derived: 10
SESSION_ID in base: 10
Can you please help?
The global variable in a module is merely an attribute (i.e. a member
entity) of that module.
As result of that when you use import *, the new local module global SESSION_ID is created, so the SESSION_ID in the base is immune to the changes you are doing in the Derived.
Basically, modifying base.SESSION_ID don't require usage of the global statement in the Derived.py, adjusting import is enough, see code below:
from settings import base
class Derived():
def m2(self):
base.SESSION_ID = 10
print "SESSION_ID in derived: ", base.SESSION_ID
def main():
c2 = Derived()
c2.m2()
base.m1()
if __name__ == "__main__":
main()
Your Derived class is not derived from anything inside Base.py. Here, you are just calling a basic function from Base from within Derived, nothing more.
Here is an example on class inheritance in Python3 :
>>> class Base():
>>> SESSION = 42
>>>
>>> def print_session(self):
>>> print("Base session : %d" % self.SESSION)
>>>
>>> class Derived(Base):
>>> SESSION = 999
>>>
>>> d = Derived()
>>> d.print_session()
Base session : 999
I would avoid using global and class-scoped variables if at all possible. These can make your program harder to understand (if something else changes a global underneath you it's hard to notice) and test (you need to reset all global state between every test; it's often easier to just create new empty state).
I might restructure this example by creating a state object:
class State:
def __init__(self):
self.session_id = ''
And then making that explicitly be a property, say, of the base class:
class Base:
def __init__(self, state):
self.state = state
def m1(self):
print("SESSION_ID in base: " + str(self.state.session_id))
class Derived(Base):
def m2(self):
self.state.session_id = '10'
print("SESSION_ID in derived: " + str(self.state.session_id))
Then in your main function you need to explicitly create the state object and pass it in
def main():
state = State()
c2 = Derived(state)
c2.m2()
c2.m1()
But, critically, your tests don't need to worry about state leakage
def test_m2():
state = State()
obj = Derived(state)
obj.m2()
assert state.session_id == '10'
def test_m1():
state = State()
obj = Base(state)
obj.m1()
# If the session ID was a global or a class variable,
# you'd get a different result if m2() was called or not
assert state.session_id == ''
Is setup.inQ different from complete.inQ?
If I put something in one queue, it wouldn't show up in the other queue, correct?
import Queue
class Factory:
name = ""
inQ = Queue.Queue()
outQ = Queue.Queue()
def worker(self): pass
#staticmethod
def getFactory(factory_name):
if factory_name == "setup":
return SetupFactory()
elif factory_name == "dispatch":
return DispatchFactory()
elif factory_name == "complete":
return CompleteFactory()
else:
return None
class SetupFactory(Factory):
name = "setup"
def worker(self):
#extend
class DispatchFactory(Factory):
name = "dispatch"
def worker(self):
#extend
class CompleteFactory(Factory):
name = "complete"
def worker(self):
#extend
setup = Factory.getFactory("setup")
complete = Factory.getFactory("complete")
This is easy enough to test:
>>> import Queue
>>> class A(object):
... q = Queue.Queue()
...
>>> class B(A):
... pass
...
>>> a = A()
>>> b = B()
>>> b.q is a.q
True
We see that the q attribute is indeed shared across subclasses. (putting things in b.q is the exact same things as putting things in a.q).
This makes sense because A.q is an attribute of the class, so it gets created when A gets created. Python doesn't create a new one when B gets created since B just inherits properties and methods from A.
Generally speaking, if you want to have a property that isn't shared across instances of a class, you'd put it in the class's initialization function (__init__) which gets called magically by python when you create an instance of a class:
class Factory(object):
name = ""
def __init__(self):
self.inQ = Queue.Queue()
self.outQ = Queue.Queue()
I'm new to Python - and just trying to better understand the logic behind certain things.
Why would I write this way (default variables are in __init__):
class Dawg:
def __init__(self):
self.previousWord = ""
self.root = DawgNode()
self.uncheckedNodes = []
self.minimizedNodes = {}
def insert( self, word ):
#...
def finish( self ):
#...
Instead of this:
class Dawg:
previousWord = ""
root = DawgNode()
uncheckedNodes = []
minimizedNodes = {}
def insert( self, word ):
#...
def finish( self ):
#...
I mean - why do I need to use __init__ -> if I can just as easily add default variables to a class directly?
When you create variables in the Class, then they are Class variables (They are common to all the objects of the class), when you initialize the variables in __init__ with self.variable_name = value then they are created per instance and called instance variables.
For example,
class TestClass(object):
variable = 1
var_1, var_2 = TestClass(), TestClass()
print var_1.variable is var_2.variable
# True
print TestClass.variable is var_1.variable
# True
Since variable is a class variable, the is operator evaluates to True. But, in case of instance variables,
class TestClass(object):
def __init__(self, value):
self.variable = value
var_1, var_2 = TestClass(1), TestClass(2)
print var_1.variable is var_2.variable
# False
print TestClass.variable is var_1.variable
# AttributeError: type object 'TestClass' has no attribute 'variable'
And you cannot access an instance variable, with just the class name.
When you write this:
class Dawg:
previousWord = ""
root = DawgNode()
uncheckedNodes = []
minimizedNodes = {}
Those are not instance variables, they're class variables (meaning: the same variables with the same values are shared between all instances of the class.) On the other hand, this:
class Dawg:
def __init__(self):
self.previousWord = ""
self.root = DawgNode()
self.uncheckedNodes = []
self.minimizedNodes = {}
... Is declaring instance variables, meaning: the values are different for each instance of the class. As you see, each snippet means a completely different thing, and you have to pick the one that is appropriate for you. Hint: most of the time you're interested in instance variables, because class variables define a kind of shared global state for your objects, which is error prone.