Методы класса и статические методы
Когда интерпретатор достигает инструкции class (а не тогда, когда происходит вызов класса), он выполняет все инструкции в ее теле от начала и до конца. Все присваивания, которые производятся в ходе этого процесса, создают имена в локальной области видимости класса, которые становятся атрибутами объекта класса.
Благодаря этому классы напоминают модули и функции:
- Подобно функциям, инструкции class являются локальными областями видимости, где располагаются имена, созданные вложенными операциями присваивания.
- Подобно именам в модуле, имена, созданные внутри инструкции class, становятся атрибутами объекта класса.
Для работы с классом питон создает отдельный объект, описывающий весь класс целиком как набор правил, а не отдельный экземпляр класса. (class object).
У этого объекта тоже могут быть свои поля и методы.
Они нужны для атрибутов и методов, которые относятся не к конкретному экземпляру, а ко всему классу целиком.
Например, для класса, описывающих дату, это может быть список названий месяцев.
Переменные класса
class Date():
month = ['январь', 'февраль', ..]
def __init__(self, day, month, year):
self.day = day
self.month = month
self.year = year
self.month_name = Date.month[month-1]
Попробуем посчитать, сколько экземпляров класса Circle было создано за время работы программы.
class Circle():
counter = 0 # сколько экземпляров класса было создано
def __init__(self, x=0, y=0, r=1):
Circle.counter += 1
c = Circle()
d = Circle()
print(
При чтении переменных идет поиск этой переменной в пространстве имен.
При = изменяется сам объект. (Быть может создается атрибут этого объекта).
class A(object):
shared_data = 42
x = A()
y = A()
print(x.shared_data, y.shared_data, A.shared_data) # 42, 42, 42
A.shared_data = 99 # А - объект - класс
print(x.shared_data, y.shared_data, A.shared_data) # 99, 99, 99
# x - объект - экземпляр класса
x.shared_data = 100 # создали новый атрибут ЭКЗЕМПЛЯРА класса
print(x.shared_data, y.shared_data, A.shared_data) # 100, 99, 99
В классе и экземпляре класса может быть поле с одинаковым именем (не пишите так!):
class B(object):
data = 'shared' # присваивание атрибуту класса
def __init__(self, data):
self.data = data # присваивание атрибуту экземпляра
def prn(self):
print(self.data, B.data) # атрибут экземпляра, атрибут класса
x = B(1)
y = B(2)
x.prn() # 1 shared
y.prn() # 2 shared
Вызов методов
Для любого объекта класса класс
допустимы варианты вызова метода экземпляра класса:
экземпляр.метод(аргументы...)
класс.метод(экземпляр, аргументы...)
Например:
class A(object):
def func(self, value):
print(value)
x = A()
x.func('первый вызов') # первый вызов
A.func(x, 'второй вызов') # второй вызов
методы класса и статические методы
@classmethod можно переопределить в наследнике класса
У метода класса есть cls, но нет self
@staticmethod нельзя переопределить при наследовании классов
class Date(object):
def __init__(self, day=0, month=0, year=0):
self.day = day
self.month = month
self.year = year
@classmethod
def from_string(cls, date_as_string):
day, month, year = map(int, date_as_string.split('-'))
date1 = cls(day, month, year)
return date1
@staticmethod
def is_date_valid(date_as_string):
day, month, year = map(int, date_as_string.split('-'))
return day <= 31 and month <= 12 and year <= 3999
date2 = Date.from_string('11-09-2012')
is_date = Date.is_date_valid('11-09-2012')
Пример static factory
Допустим, у нас должно быть не более 1 экземпляра данного класса.
Когда какой метод делаем?
Метод:
- экземпляра класса (self) - функция обращается к атрибутам экземпляра;
- класса - функция не обращается к атрибутам экземпляра класса, но обращается к атрибутам класса;
- static - функция не обращается ни к каким атрибутам класса или объекта.