Types of Attributes
There are two types of attributes: Class and Instance.
Class attributes are variables shared by all the instances (unique objects) in a class. They are typically things like constants, or information about how many objects of the class exists. For example a Stop_Light class may have the class attribute
light _color = ['red', 'yellow', 'green'] to ensure all instances of Stop_Light use the same colors in the same order. A more complex version of our Student class might have a list of all in-use student_ids to ensure they are all unique.
Class attributes are denoted on the UML diagram by underlining the attribute. In our example the Main-class contains Class Attributes.
Many programming languages include a special keyword
static. In those languages, a
static attribute or method is what Python calls a class attribute or method. CLass items are indicated on UML diagram by an underline. For Python, static-method and static-attribute are synonymous with class-.1
In Python, any attributes declared outside of a method are class attributes, but they can be considered the same as static attributes until they are overwritten by an instance. Here’s an example:
class Stat: x = 5 # class or static attribute def __init__(self, an_y): self.y = an_y # instance attribute
In this class, we’ve created a class attribute named
x, and a normal attribute named
y. Here’s a
main() method that will help us explore how the static keyword operates:
from Stat import * class Main: def main(): some_stat = Stat(7) another_stat = Stat(8) print(some_stat.x) # 5 print(some_stat.y) # 7 print(another_stat.x) # 5 print(another_stat.y) # 8 Stat.x = 25 # change class attribute for all instances print(some_stat.x) # 25 print(some_stat.y) # 7 print(another_stat.x) # 25 print(another_stat.y) # 8 some_stat.x = 10 # overwrites class attribute in instance print(some_stat.x) # 10 (now an instance attribute) print(some_stat.y) # 7 print(another_stat.x) # 25 (still class attribute) print(another_stat.y) # 8 if __name__ == "__main__": Main.main()
First, we can see that the attribute
x is set to 5 as its default value, so both objects
another_stat contain that same value. Interestingly, since the attribute
x is static, we can access it directly from the class
Stat, without even having to instantiate an object. So, we can update the value in that way to 25, and it will take effect in any objects instantiated from
Below that, we can update the value of
x attached to
some_stat to 10, and we’ll see that it now creates an instance attribute for that object that contains 10, shadowing the previous class attribute. The value attached to
another_stat is unchanged.
You should avoid shadowing class attributes.
Python also allows us to create class methods that work in a similar way:
class Stat: x = 5 # class or static attribute def __init__(self, an_y): self.y = an_y # instance attribute def sum(a): return Stat.x + a
We have now added a class method
sum() to our
In addition, it is important to remember that a static method cannot access any non-static attributes or methods, since it doesn’t have access to an instantiated object in the
As a tradeoff, we can call class method without instantiating the class either, as in this example:
from Stat import * class Main: def main(): # other code omitted Stat.x = 25 moreStat = Stat(7) print(moreStat.sum(5)) # 30 print(Stat.sum(5)) # 30 if __name__ == "__main__": Main.main()
Python supports an alternate syntax for methods. This form has not been widely adopted.
class Demo: class_count = 0 # a class variable def __init__(): self.name = None def instance(self, name): # an instance method (note the self parameter) # call <variable>.instance("text") self.name = name # instance attribute Demo.class_count += 1 # access a class attribute via class name @classmethod def print_count(cls): # class method # call Demo.print_count() print (cls.class_count) # access class variable via 'cls' @staticmethod def total_number(): # static method # call Demo.total_number return Demo.class_count # access a class attribute via class name
There is no expressive power difference between an
@staticmethod–the can access exactly the same things using slightly different syntax. The
@staticmethod is called a decorator. The decorators tell the Python interpreter to handle the item that follows in a special way.
By convention, the object oriented programs start with a static main methods. We will follow that convention.
UML Class Diagrams
UML neatly side steps the static-vs-class nomenclature debate by using the term “classifer” for any item which belongs to the class and not the instance. According to the UML specification, any “classifer” items should be underlined, as in this sample UML diagram below:
Type (or cut and paste) the code for the Stats class (in static/Stat.py) and Main (in static Main.py). Mark the
main() method with an
@staticmethod decorator. Now, we can use the buttons below to run the sample files open to the left to explore using class attributes and methods.
There are technical differences in the way languages store and access static and class items at the machine code level. We will ignore these differences. ↩︎