Variables declared inside the class definition, but not inside a method are class or static variables:
>>> class MyClass:
... i = 3
...
>>> MyClass.i
3
As @millerdev points out, this creates a class-level i variable, but this is distinct from any instance-level i variable, so you could have
>>> m = MyClass()
>>> m.i = 4
>>> MyClass.i, m.i
>>> (3, 4)
This is different from C++ and Java, but not so different from C#, where a static member can't be accessed using a reference to an instance.
See what the Python tutorial has to say on the subject of classes and class objects.
@Steve Johnson has already answered regarding static methods, also documented under "Built-in Functions" in the Python Library Reference.
class C:
@staticmethod
def f(arg1, arg2, ...): ...
@beidy recommends classmethods over staticmethod, as the method then receives the class type as the first argument.
Answer from Blair Conrad on Stack OverflowVariables declared inside the class definition, but not inside a method are class or static variables:
>>> class MyClass:
... i = 3
...
>>> MyClass.i
3
As @millerdev points out, this creates a class-level i variable, but this is distinct from any instance-level i variable, so you could have
>>> m = MyClass()
>>> m.i = 4
>>> MyClass.i, m.i
>>> (3, 4)
This is different from C++ and Java, but not so different from C#, where a static member can't be accessed using a reference to an instance.
See what the Python tutorial has to say on the subject of classes and class objects.
@Steve Johnson has already answered regarding static methods, also documented under "Built-in Functions" in the Python Library Reference.
class C:
@staticmethod
def f(arg1, arg2, ...): ...
@beidy recommends classmethods over staticmethod, as the method then receives the class type as the first argument.
@Blair Conrad said static variables declared inside the class definition, but not inside a method are class or "static" variables:
>>> class Test(object):
... i = 3
...
>>> Test.i
3
There are a few gotcha's here. Carrying on from the example above:
>>> t = Test()
>>> t.i # "static" variable accessed via instance
3
>>> t.i = 5 # but if we assign to the instance ...
>>> Test.i # we have not changed the "static" variable
3
>>> t.i # we have overwritten Test.i on t by creating a new attribute t.i
5
>>> Test.i = 6 # to change the "static" variable we do it by assigning to the class
>>> t.i
5
>>> Test.i
6
>>> u = Test()
>>> u.i
6 # changes to t do not affect new instances of Test
# Namespaces are one honking great idea -- let's do more of those!
>>> Test.__dict__
{'i': 6, ...}
>>> t.__dict__
{'i': 5}
>>> u.__dict__
{}
Notice how the instance variable t.i got out of sync with the "static" class variable when the attribute i was set directly on t. This is because i was re-bound within the t namespace, which is distinct from the Test namespace. If you want to change the value of a "static" variable, you must change it within the scope (or object) where it was originally defined. I put "static" in quotes because Python does not really have static variables in the sense that C++ and Java do.
Although it doesn't say anything specific about static variables or methods, the Python tutorial has some relevant information on classes and class objects.
@Steve Johnson also answered regarding static methods, also documented under "Built-in Functions" in the Python Library Reference.
class Test(object):
@staticmethod
def f(arg1, arg2, ...):
...
@beid also mentioned classmethod, which is similar to staticmethod. A classmethod's first argument is the class object. Example:
class Test(object):
i = 3 # class (or static) variable
@classmethod
def g(cls, arg):
# here we can use 'cls' instead of the class name (Test)
if arg > cls.i:
cls.i = arg # would be the same as Test.i = arg1

Can someone explain how object/instance variables vs class/static variables work in Python?
What is the Python equivalent of static variables inside a function? - Stack Overflow
AWS Lambda and static variables
Python - How to how to reset class attributes?
I don't believe lazypenguin18 or Arxae are correct.
First of all, def attack(attack): is kind of a weird method declaration.
When you make a class, all methods (functions that are a part of the class) have the first parameter be the object in question. Essentially, every time you call a method of a class, you're calling the function and giving the object itself as an argument. For example, calling MONSTER.attack() is calling attack(Monster-object). This lets you access the attributes (variables that are a part of the class) of the object. The interpreter automatically inserts this for you, so even though the method declaration is def attack(self):, All you run is MONSTER.attack(). By using the period syntax, you are giving the self parameter its argument. Although there is nothing wrong with naming that parameter attack, it strikes me as unfamiliarity with how python classes work, but that's okay. It's a little obscure. To be specific, you're supposed to access attributes of an object by using whatever the first parameter is named (Normally this is named self for convention, but in this case you have it named attack). This sort of leads into my next point, which is what I think is causing your error.
In Python, this is how you're supposed to initialize attributes (I'm going to make a pretend player, just to stick with your theme):
class Player(object):
def __init__(self): #This is the "constructor"
self.gun = Gun() #Lets pretend Gun is another classI have a feeling you have it written like this:
class Player(object):
gun = Gun()
This works, but is not what you want. When you create attributes inside the class like that, not using the above (Specifically, you can do it anytime using the self reference, but __init__ is called when the object is created so it's handy to do it then), what you create are class attributes. These are variables that only exist once for all the objects that exist of this kind. For example, if we have a gun defined like the above (And not using the self reference), then if we create 5 Player objects, they would all be using the same gun. If we modify gun, perhaps player1.gun = 5, then player2.gun would also be 5, and so on.
If you were to use the first format (With the self.gun reference), then player1.gun = 5 would leave player2.gun unchanged from its original value. They would be separate, and unique to each object.
I believe what you're doing is you've initialized the Monster HP attribute as a class attribute, and this is remaining at 0 because it is being changed for the whole class, and not just that individual object.
With this in mind, you will have to change your code a bit. I notice this in this part, print "You attack with your", gun.title(), you will have to change gun.title() to attack.gun.title(), but it would be best if you renamed the attack parameter to self.
There are two other, big things I notice in your code, but I think I'm about to hit the character limit any moment. Sorry if this was a little long winded, if you'd like me to elaborate, explain, or even talk about those two other things, feel free to drop me a PM.
More on reddit.comSo I come from a Java background where defining, declaring and accessing static and instance level variables are pretty much a straightforward process. I want to be able to understand OOP concepts of Python properly so I have been doing some practice.
I have a class:
class A:
def init(self): pass
def someFunc(self): self.var1 += 1
I create an object of this class and call the someFunc() method:
a = A() a.someFunc()
It gives me an error. Ok, fair enough since I haven't declared a self.var1 variable yet.
Consider another example.
class A:
var1 = 10
def init(self): pass
def someFunc(self): self.var1 += 1
Now when I do this:
a = A() a.someFunc() Output: 11
I know that variables defined just below the class definition are class/static variables. And to access them you have to do A.var1
But why does it not give me an error now? I haven't created a object/instance level self.var1 variable yet, just a class level variable var1.
And when I call A.var1 the output is 10. Why is the output not the same as a.var1?
Does python automatically use the class level variable with the same name since there is no instance level variable defined with the same name? And does that in turn become a different variable from the class level variable?
Can someone please elaborate?
A bit reversed, but this should work:
def foo():
foo.counter += 1
print "Counter is %d" % foo.counter
foo.counter = 0
If you want the counter initialization code at the top instead of the bottom, you can create a decorator:
def static_vars(**kwargs):
def decorate(func):
for k in kwargs:
setattr(func, k, kwargs[k])
return func
return decorate
Then use the code like this:
@static_vars(counter=0)
def foo():
foo.counter += 1
print "Counter is %d" % foo.counter
It'll still require you to use the foo. prefix, unfortunately.
(Credit: @ony)
You can add attributes to a function, and use it as a static variable.
def myfunc():
myfunc.counter += 1
print myfunc.counter
# attribute must be initialized
myfunc.counter = 0
Alternatively, if you don't want to setup the variable outside the function, you can use hasattr() to avoid an AttributeError exception:
def myfunc():
if not hasattr(myfunc, "counter"):
myfunc.counter = 0 # it doesn't exist yet, so initialize it
myfunc.counter += 1
Anyway static variables are rather rare, and you should find a better place for this variable, most likely inside a class.