classmethods Python

Содержание
Введение
Пример
Класс метод как альтернативный конструктор
Похожие статьи

Введение

Это продолжение статьи «Классы» из раздела «ООП в Python» .

Здесь вы можете прочитаь про classmethods

Обычные, иначе говоря, instance методы вы можете изучить здесь , статические здесь

Рекомендую также изучить статью «Декораторы в Python»

Пример

Класс методы принимают в качестве аргумента не объект класса, а сам класс.

# Class Methods part 1. Total 8 class Employee: num_of_emps = 0 raise_amt = 1.04 def __init__(self, first, last, pay): self.first = first self.last = last self.pay = pay self.email = first + '.' + last + '@company.com' Employee.num_of_emps += 1 def fullname(self): return f'{self.first} {self.last}' def apply_raise(self): self.pay = int(self.pay * self.raise_amt) # regular method automatically takes an instance as an argument # by convention it is called 'self' # class method takes class as an argument @classmethod def set_raise_amt(cls, amount): cls.raise_amt = amount emp_1 = Employee('Balda', 'Worker', 50000) emp_2 = Employee('Test', 'User', 60000) print(Employee.raise_amt) # 1.04 print(emp_1.raise_amt) # 1.04 print(emp_2.raise_amt) # 1.04 Employee.set_raise_amt(1.05) print(Employee.raise_amt) # 1.05 print(emp_1.raise_amt) # 1.05 print(emp_2.raise_amt) # 1.05 # Можно применить класс метод к объекту # изменения будут для всего класса а не только # для этого объекта. Поэтому смысла так делать нет. # В следующем примере применим к emp_1 и убедимся что 1.06 станет у всех emp_1.set_raise_amt(1.06) print(Employee.raise_amt) # 1.06 print(emp_1.raise_amt) # 1.06 print(emp_2.raise_amt) # 1.06

python classmethod_example.py

1.04 1.04 1.04 1.05 1.05 1.05 1.06 1.06 1.06

Класс метод как альтернативный конструктор

Если вам нужно получить данные из внешнего источника, например импортируете из .csv файла и потом создать из них объекты, возможно этот способ подойдёт.

Предположим, данные приходят в виде строк, где значения разделены с помощью -

emp_str_1 = 'John-Doe-70000' emp_str_2 = 'Steve-Smith-30000' emp_str_3 = 'Jane-Doe-90000' first, last, pay = emp_str_1.split('-') new_emp_1 = Employee(first, last, pay) print(new_emp_1.email) print(new_emp_1.pay)

python classmethod_example.py

John.Doe@company.com 70000

Чтобы ускорить создание объектов можно написать класс метод

@classmethod def from_string(cls, emp_str): first, last, pay = emp_str.split('-') return cls(first, last, pay) emp_str_1 = 'John-Doe-70000' new_emp_1 = Employee.from_string(emp_str_1) print(new_emp_1.email) print(new_emp_1.pay)

python classmethod_example.py

John.Doe@company.com 70000

Похожий пример можно увидеть в библиотеке datetime

class date: """Concrete date type. Constructors: __new__() fromtimestamp() today() fromordinal() Operators: __repr__, __str__ __eq__, __le__, __lt__, __ge__, __gt__, __hash__ __add__, __radd__, __sub__ (add/radd only with timedelta arg) Methods: timetuple() toordinal() weekday() isoweekday(), isocalendar(), isoformat() ctime() strftime() Properties (readonly): year, month, day """ __slots__ = '_year', '_month', '_day', '_hashcode' def __new__(cls, year, month=None, day=None): """Constructor. Arguments: year, month, day (required, base 1) """ if (month is None and isinstance(year, (bytes, str)) and len(year) == 4 and 1 <= ord(year[2:3]) <= 12): # Pickle support if isinstance(year, str): try: year = year.encode('latin1') except UnicodeEncodeError: # More informative error message. raise ValueError( "Failed to encode latin1 string when unpickling " "a date object. " "pickle.load(data, encoding='latin1') is assumed.") self = object.__new__(cls) self.__setstate(year) self._hashcode = -1 return self year, month, day = _check_date_fields(year, month, day) self = object.__new__(cls) self._year = year self._month = month self._day = day self._hashcode = -1 return self # Additional constructors @classmethod def fromtimestamp(cls, t): "Construct a date from a POSIX timestamp (like time.time())." y, m, d, hh, mm, ss, weekday, jday, dst = _time.localtime(t) return cls(y, m, d) …

Как видно из этого отрывка кода - у класса date есть основной конструктор __new__() и несколько дополнительных.

На примере дополнительного конструктора fromtimestamp видно, что он реализован с помощью декоратора classmethod

Похожие статьи
ООП в Python
Классы
Методы
class variables
class methods
Статические методы
Наследование
Специальные методы
Декоратор property
Python
Функции
super()