Шаг 88.
Python: тонкости программирования. Классы и ООП. Методы экземпляра, класса и статические методы. Когда использовать статические методы

    На этом шаге мы рассмотрим области применения таких методов.

    Продолжим аналогию с пиццей. Вот что мы сделаем:

>>> import math
>>> class Pizza:
	def __init__(self, radius, ingredients):
		self.radius = radius
		self.ingredients = ingredients
	def __repr__(self):
		return (f'Pizza({self.radius!r},'
			f'{self.ingredients!r})')
	def area(self):
		return self.circle_area(self.radius)
	@staticmethod
	def circle_area(r):
		return r ** 2 * math.pi

   

    Итак, что же тут изменилось? Прежде всего, изменился конструктор и метод __repr__, и теперь они принимают дополнительный аргумент radius.

    Также добавлен метод экземпляра area(), который вычисляет и возвращает площадь пиццы. Это также будет подходящей кандидатурой для @property... но постойте, это же просто игрушечный пример.

    Вместо того чтобы вычислять площадь непосредственно внутри метода area() при помощи общеизвестной формулы площади круга, вынесем это вычисление в отдельный статический метод circle_area().

    Давайте его испытаем!

>>> p = Pizza(4, ['моцарелла', 'помидоры'])
>>> p
Pizza(4,['моцарелла', 'помидоры'])
>>> p.area()
50.26548245743669
>>> Pizza.circle_area(4)
50.26548245743669

    Несомненно, этот пример по-прежнему довольно упрощенный, но он поможет объяснить некоторые преимущества, предоставляемые статическими методами.

    Как мы узнали, статические методы не могут получать доступ к состоянию класса или экземпляра, потому что они не принимают аргумент cls или self. Этот факт является большим ограничением - но он также является замечательным сигналом, который обозначает, что тот или иной метод независим от всего остального вокруг него.

    Из примера выше совершенно ясно, что circle_area() никак не может модифицировать класс или экземпляр класса. (Разумеется, это ограничение всегда можно обойти при помощи глобальной переменной, но это уже к делу не относится.)

    Итак, почему же это полезно?

    Обозначение метода как статического не просто подсказка, что этот метод не сможет модифицировать состояние экземпляра или класса. Но, как вы убедились, это ограничение также подкрепляется во время выполнения программы Python.

    Такие приемы дают четкое представление о составных частях вашей архитектуры классов для того, чтобы процесс новой разработки естественным образом направлялся в пределах этих границ. Безусловно, эти ограничения достаточно легко нарушить. Но на практике они нередко помогают избежать непреднамеренных модификаций, которые идут вразрез с первоначальным проектом.

    Другими словами, использование статических методов и методов класса способствует передаче замысла разработчика, при этом достаточно подкрепляя этот замысел, чтобы избежать большинства ошибок "по недоразумению" и ошибок, которые разрушили бы проект.

    При экономном применении и только в тех случаях, когда это имеет смысл, написание части своих методов таким вот образом может предоставить преимущества в сопровождении и уменьшит вероятность того, что другие разработчики будут использовать ваши классы неправильно.

    Статические методы также обладают преимуществами в том, что касается написания тестового программного кода. Поскольку метод circle_area() абсолютно независим от остальной части класса, его намного легче протестировать.

    Нам не придется переживать по поводу настройки полного экземпляра класса перед тем, как мы сможем протестировать этот метод в модульном тесте. Мы просто можем действовать подобно тому, как мы действовали бы при тестировании обычной функции. И опять-таки, это облегчает сопровождение кода в будущем и обеспечивает связь между объектно-ориентированным и процедурным стилями программирования.

    На следующем шаге мы подитожим изученный материал.




Предыдущий шаг Содержание Следующий шаг