Class Definition
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
|
# mymodule.py
class MyParentClass:
"""A (parent) class to inherit from."""
def __init__(self, parent_arg):
print(f"Parent class constructor has been called with this argument: {parent_arg}")
class MyClass(MyParentClass):
"""Template class."""
my_class_variable = None
def __init__(self, arg):
"""Initialize instance object of class."""
# assignment of instance variable
self.my_instance_variable = arg
# assignement of class variable
self.__class__.my_class_variable = 'foo'
# call the __init__() method of the parent class
super().__init__("fuzzbuzz")
def __repr__(self):
"""String representation of class."""
return (f'<{self.__class__.__name__}('
f'my_instance_variable={self.my_instance_variable!r}, '
f'my_class_variable={self.__class__.my_class_variable!r})>'
)
def a_method(self, obj_arg, cls_arg):
"""A standard instance method with access to class and object state."""
self.my_instance_variable = obj_arg
self.__class__.my_class_variable = cls_arg
return 'instance method called', self
@classmethod
def a_classmethod(cls, cls_arg):
"""A classmethod with access to the class state only."""
cls.my_class_variable = cls_arg
return 'class method called', cls
@classmethod
def a_factoryfunction(cls, arg):
"""A factory function returning an instance of the class."""
return cls(arg)
@staticmethod
def a_staticmethod():
"""A static method with no access to class or object state."""
return 'static method called'
|
Variables
Class Variables
Class variables apply to all objects instanciated from the class. Changing it in one object changes it for all objects!
Class variable can be reached through the class or the instanciated object:
1
2
3
4
5
6
7
8
|
>>> from mymodule import MyClass
>>> arg = 'bar'
>>> my_obj = MyClass(arg)
Parent class constructor has been called with this argument: fuzzbuzz
>>> my_obj.my_class_variable
'foo'
>>> MyClass.my_class_variable
'foo'
|
Instance Variables
Instance valiables are specific to the object. Changing it in one object, no other object instanciated from the same class is effected!
Instance variables can only be reached through the instanciated object:
1
2
3
4
5
6
7
8
|
>>> from mymodule import MyClass
>>> arg = 'bar'
>>> my_obj = MyClass(arg)
Parent class constructor has been called with this argument: fuzzbuzz
>>> my_obj.my_instance_variable
'bar'
>>> MyClass.my_instance_variable
AttributeError...
|
WARNING:
Do not accidentally shadow a class variable with an instance variable of the same name!
Methods
Instance or Object Methods
Call through the Instance
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
>>> from mymodule import MyClass
>>> arg = 'bar'
>>> my_obj = MyClass(arg)
Parent class constructor has been called with this argument: fuzzbuzz
>>> my_obj.my_instance_variable
'bar'
>>> MyClass.my_class_variable
'foo'
>>> my_obj.a_method('ham', 'eggs')
('instance method called', <MyClass(my_instance_variable='ham', my_class_variable='eggs')>)
>>> my_obj.my_instance_variable
'ham'
>>> MyClass.my_class_variable
'eggs'
|
Call through the Class
Calling the standard method through the class fails:
1
2
3
|
>>> from mymodule import MyClass
>>> MyClass.a_method('ham', 'eggs')
TypeError: method() missing 1 required positional argument: 'cls_arg'
|
The error indicates that there is one argument missing. It is actually not cls_arg
but self
, the very first argument to this method and the reference to an class instance:
1
2
3
4
5
6
|
>>> from mymodule import MyClass
>>> arg = 'bar'
>>> my_obj = MyClass(arg)
Parent class constructor has been called with this argument: fuzzbuzz
>>> MyClass.a_method(my_obj, 'ham', 'eggs')
('instance method called', <MyClass(my_instance_variable='ham', my_class_variable='eggs')>)
|
NOTE:
The syntax
1
2
|
my_obj = MyClass(arg)
MyClass.a_method(my_obj, 'ham', 'eggs')
|
is equivalent to
1
2
|
my_obj = MyClass(arg)
my_obj.a_method('ham', 'eggs')
|
Class Methods
Call through the Instance
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
>>> from mymodule import MyClass
>>> arg = 'bar'
>>> my_obj = MyClass(arg)
Parent class constructor has been called with this argument: fuzzbuzz
>>> my_obj.my_instance_variable
'bar'
>>> MyClass.my_class_variable
'foo'
>>> my_obj.a_classmethod('jam')
('class method called', <class 'mymodule.MyClass'>)
>>> my_obj.my_instance_variable
'bar'
>>> MyClass.my_class_variable
'jam'
|
Call through the Class
Calling the class method through the class works just fine:
1
2
3
4
5
|
>>> from mymodule import MyClass
>>> MyClass.a_classmethod('honey')
('class method called', <class 'mymodule.MyClass'>)
>>> MyClass.my_class_variable
'honey'
|
Factory Functions
Class methods can be utilized to implement the factory function pattern:
1
2
3
4
5
|
>>> from mymodule import MyClass
>>> arg = 'cheese'
>>> MyClass.a_factoryfunction(arg)
Parent class constructor has been called with this argument: fuzzbuzz
<MyClass(my_instance_variable='cheese', my_class_variable='foo')>
|
Static Methods
Call through the Instance
1
2
3
4
5
6
|
>>> from mymodule import MyClass
>>> arg = 'bar'
>>> my_obj = MyClass(arg)
Parent class constructor has been called with this argument: fuzzbuzz
>>> my_obj.a_staticmethod()
'static method called'
|
Call through the Class
1
2
3
|
>>> from mymodule import MyClass
>>> MyClass.a_staticmethod()
'static method called'
|