Отличный вопрос! То, что вы ищете, может быть легко сделано с помощью дескрипторов .
Дескрипторы - это объекты Python, которые реализуют протокол дескриптора , обычно начинающийся с __get__()
.
Они существуют, в основном, для установки в качестве атрибута класса в разных классах. При обращении к ним вызывается их метод __get__()
с передачей класса экземпляра и владельца.
class DifferentFunc:
"""Deploys a different function accroding to attribute access
I am a descriptor.
"""
def __init__(self, clsfunc, instfunc):
# Set our functions
self.clsfunc = clsfunc
self.instfunc = instfunc
def __get__(self, inst, owner):
# Accessed from class
if inst is None:
return self.clsfunc.__get__(None, owner)
# Accessed from instance
return self.instfunc.__get__(inst, owner)
class Test:
@classmethod
def _get_other_thing(cls):
print("Accessed through class")
def _get_other_thing_inst(inst):
print("Accessed through instance")
get_other_thing = DifferentFunc(_get_other_thing,
_get_other_thing_inst)
А теперь результат:
>>> Test.get_other_thing()
Accessed through class
>>> Test().get_other_thing()
Accessed through instance
Это было легко!
Кстати, вы заметили, что я использовал __get__
в функции класса и экземпляра? Угадай, что? Функции также являются дескрипторами, и вот как они работают!
>>> def func(self):
... pass
...
>>> func.__get__(object(), object)
<bound method func of <object object at 0x000000000046E100>>
После доступа к атрибуту функции вызывается его __get__
, и таким образом вы получаете привязку функции.
Для получения дополнительной информации я настоятельно рекомендую прочитать руководство по Python и "How-To" , ссылки на которые приведены выше. Дескрипторы являются одной из самых мощных функций Python и едва известны.
Почему бы не установить функцию при создании экземпляра?
или Почему бы не установить self.func = self._func
внутри __init__
?
Установка функции при создании экземпляра сопряжена с рядом проблем:
self.func = self._func
вызывает циклическую ссылку. Экземпляр хранится внутри объекта функции, возвращаемого self._func
. Это, с другой стороны, сохраняется в экземпляре во время назначения. Конечный результат заключается в том, что экземпляр ссылается на себя и очищается гораздо медленнее и тяжелее.
- Другой код, взаимодействующий с вашим классом, может попытаться вывести функцию прямо из класса и использовать
__get__()
, который является обычным ожидаемым методом, чтобы связать ее. Они получат неправильную функцию.
- Не будет работать с
__slots__
.
- Хотя с дескрипторами необходимо понимать механизм, его установка на
__init__
не так чиста и требует установки нескольких функций на __init__
.
- Занимает больше памяти. Вместо того, чтобы хранить одну функцию, вы сохраняете связанную функцию для каждого экземпляра.
- Не будет работать с свойствами .
Есть еще много чего, что я не добавил по мере того, как список можно продолжать и продолжать.