Хотя я не рекомендую это !!!!!!!!!!!!!!!!!!!!!
этосвоего рода приближается к реализации поведения вызова специального метода для каждого имени, которое не соответствует вызываемому атрибуту / методу.Конечно, они все еще не имеют отдельных пространств имен, так что это может показаться немного странным.Он работает путем переопределения __getattribute__
, который работает на более низком уровне, чем __getattr__
, он пытается извлечь атрибут в случае неудачи, возвращает специальный карри-метод для вызова с именем, с которым вы его вызвали, если он успешен, он передает его, еслив противном случае он вызывает результат с помощью прокси-объекта, который впоследствии действует почти таким же образом, за исключением того, что он реализует вызов с вашим специальным методом.
Он не позволяет вам получить доступ к вызывающему объекту, потому что я не мог 'Не подумайте о хорошем способе сделать это без утечки памяти (вызывающего объекта), если это уже не подлежащий вызову атрибут, который вы сохраняете (единственное, о чем я могу подумать, - это запустить новый поток, который удаляет его через минутук тому времени вы, вероятно, уже назвали его, если не используете его в замыкании, которое не будет поддерживаться в этом случае).
Редактировать: я забыл, что вызываемое может иметь некоторые ложные срабатывания.
зависит от http://pypi.python.org/pypi/ProxyTypes библиотеки
from peak.util.proxies import ObjectWrapper
from functools import partial
def m(name, *args, **kwargs):
print(name,repr(args),repr(kwargs))
class CallProxy(ObjectWrapper):
def __init__(self, obj, m, method_name):
ObjectWrapper.__init__(self, obj)
object.__setattr__(self, "_method_name", method_name)
object.__setattr__(self, "_m", m)
def __call__(self, *args, **kwargs):
return self._m(self._method_name, *args,**kwargs)
class Y(object):
def __init__(self):
self.x = [3]
def __getattribute__(self, name):
try:
val = object.__getattribute__(self, name)
if not callable(val):
return CallProxy(val, m, name)
else:
return val
except AttributeError:
return partial(m, name)
In [2]: y=Y()
In [3]: y.x
Out[3]: [3]
In [4]: y.z
Out[4]: <functools.partial at 0x2667890>
In [5]: y.zz([12])
('zz', '([12],)', '{}')
In [6]: y.x.append(5)
In [7]: y.x
Out[7]: [3, 5]
In [8]: y.x(1,2,3,key="no")
('x', '(2, 3)', "{'key': 'no'}")