Classnames should be nouns like "Person", "User", "Connector", etc.
It should help the reader to differ between classes, objects, functions.
The functions
classmethod
,
staticmethod
and
property
are decorators.
A decorator is a function, which takes another function and returns the value of the taken function.
The simplest possible closure, which can used as decorator:
def wrapper(func):
def inner():
result = func()
return result
return inner
def foo():
return 42
wrapped_foo = wrapper(foo)
The function wrapper takes as argument the function.
Inside the function a
inner
function is created,
which calls the
nonlocal
func.
Nonlocal means, that the name is not in globals nor in locals.
In simple word: The function
inner
has access to the arguments of wrapper.
The wrapper returns the function inner, but it is not called.
wrapped_foo
is now the function
inner
.
When the function
wrapped_foo
is called, the function
inner
returns the result from
func
(in this case the function
foo
).
Instead of calling the wrapper with the function, we got syntactical sugar for it:
@wrapper
def foo():
return 42
# is the same like
foo = wrapper(foo)
This gives us the ability to change functions without changing the code inside of a function.
I helps to change the behavior of a function.
This is where the built-in functions
classmethod
,
staticmethod
and
property
comes in place.
This functions changes the behavior of methods:
classmethod
: The first argument is the class-object itself
staticmethod
: No first argument of class or instance. It's a pure function without any access to the class or instance.
property
: Converts a method into an attribute. This is often used, when you want to protect attributes against overwriting. Also assigning can be controlled. For example a class needs to store a temperature in Kelvin, but the input is in Celsius.
Here an example class:
class A:
def normal_method(self):
print(self)
@classmethod
def class_method(cls):
print(cls)
@staticmethod
def static_method():
print('Static Method')
@property
def prop(self):
return 42
@prop.setter
def prop(self, value):
return f'Set to {value}'
Methods:
Output:
Method: class_method <bound method A.class_method of <class '__main__.A'>>
Method: normal_method <function A.normal_method at 0x7fa22539c620>
Method: prop <property object at 0x7fa225390ae8>
Method: static_method <function A.static_method at 0x7fa225cfd0d0>
Bound method means, that the first argument of the function is a class or instance, which is implicit.
The name
self
for instances and
cls
for class is a naming convention in Python.
It's possible to call them
this
like in JavaScript. But don't do this.
Just play a little bit around with classes to learn this tricks.
PS: In my text I wrote sometimes functions instead of methods. Technically a method is function, but in oop sense we call it method. Another addition: Everything in Python is an object, even classes, functions, exceptions, datatypes. Names are pointing to the objects. An object can have more than one name. When I say function
wrapped_function
, I mean the name
wrapped_function
which points to the function, which lives in your memory.