Skip to content
This repository was archived by the owner on Jul 2, 2024. It is now read-only.

Commit 09abc9a

Browse files
committed
Added class decorators: classmethod, staticmethod, property
Signed-off-by: Serhii Horodilov <sgorodil@gmail.com>
1 parent 66510ce commit 09abc9a

File tree

2 files changed

+103
-5
lines changed

2 files changed

+103
-5
lines changed

src/basics/decorators.txt

Lines changed: 96 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,7 @@ the function execution for some time:
312312
from typing import Callable
313313

314314

315-
def defer(seconds: int = 3) -> Callable:
315+
def slow_down(seconds: int = 3) -> Callable:
316316
def decorator(func: Callable) -> Callable:
317317
def wrapper(*args, **kwargs):
318318
started_at = time.perf_counter()
@@ -328,19 +328,111 @@ the function execution for some time:
328328
return decorator
329329

330330

331-
@defer()
331+
@slow_down()
332332
def function_a():
333333
return 42
334334

335335

336-
@defer(10)
336+
@slow_down(10)
337337
def function_b():
338338
return 24
339339

340-
341340
.. code-block::
342341

343342
function_a()
344343
Completed in 3.00
345344
function_b()
346345
Completed in 10.00
346+
347+
Class decorators
348+
================
349+
350+
There are some pre-defined decorators exists for usage together with classes.
351+
They are:
352+
353+
- ``classmethod``
354+
- ``staticmethod``
355+
- ``property``
356+
357+
If you develop an intuitive understanding for their differences you’ll be able to write object-oriented Python that communicates its intent more clearly and will be easier to maintain in the long run :cite:`realpython:methods-demystified`.
358+
359+
Class methods
360+
-------------
361+
362+
Instead of accepting a self parameter, class methods take a ``cls`` parameter
363+
that points to the class—and not the object instance—when the method is called.
364+
365+
Because the class method only has access to this ``cls`` argument, it can't
366+
modify object instance state. That would require access to ``self``.
367+
However, class methods can still modify class state that applies across all
368+
instances of the class.
369+
370+
The common usage for ``classmethod`` is provide alternative initializers.
371+
372+
Static methods
373+
--------------
374+
375+
This type of method takes neither a ``self`` nor a ``cls`` parameter (but of
376+
course it’s free to accept an arbitrary number of other parameters).
377+
378+
Therefore a static method can neither modify object state nor class state.
379+
Static methods are restricted in what data they can access - and they're
380+
primarily a way to namespace your methods.
381+
382+
It's tricky to explain ``staticmethod`` usage. Almost always you can create
383+
a dedicated function instead of static method. But sometimes you need to
384+
bind some logic independent from class itself or its instances to a class -
385+
it common to encapsulate it with ``staticmethod``.
386+
387+
Properties
388+
----------
389+
390+
It's a way to bind a method name to access it as an attribute. Properties are
391+
"read-only" by default. This means a value cannot be assigned to ``property
392+
member``.
393+
394+
Some examples
395+
-------------
396+
397+
.. code-block:: python
398+
399+
import datetime
400+
401+
402+
class Person:
403+
"""Person class implementation"""
404+
405+
def __init__(self, first_name: str, last_name: str) -> None:
406+
"""Initialize instance"""
407+
408+
self.first_name = first_name
409+
self.last_name = last_name
410+
411+
@classmethod
412+
def from_fullname(cls, name: str) -> "Person":
413+
"""Return a person instance"""
414+
415+
first_name, last_name = name.rsplit(" ", 1)
416+
417+
return cls(first_name, last_name)
418+
419+
@staticmethod
420+
def format_date(date: datetime.date) -> str:
421+
"""Return a formatted date as string"""
422+
423+
return date.strftime("%d-%m-%Y")
424+
425+
@property
426+
def fullname(self) -> str:
427+
"""Return person's fullname"""
428+
429+
return " ".join([self.first_name, self.last_name])
430+
431+
.. code-block::
432+
433+
>>> sh = Person("Serhii", "Horodilov")
434+
>>> vp = Person.from_fullname("Vladyslav Ponomaryov")
435+
>>> sh.fullname
436+
'Serhii Horodilov'
437+
>>> vp.fullname
438+
'Vladyslav Ponomaryov'

src/refs.bib

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,4 +101,10 @@ @misc{docs-python:function-definition
101101
@misc{refactoring.guru:decorator,
102102
title = "{Refactoring Guru: Decorator}",
103103
url = {https://refactoring.guru/design-patterns/decorator},
104-
}
104+
}
105+
106+
@misc{realpython:methods-demystified,
107+
title = "{Python's Instance, Class, and Static Methods Demystified}",
108+
author = "{Dan Bader}",
109+
url = {https://realpython.com/instance-class-and-static-methods-demystified/},
110+
}

0 commit comments

Comments
 (0)