Я пытался найти способ реализовать оболочку класса, которая работает для любого данного класса в течение многих часов.Все решения, которые я видел, требуют либо доступа к определению класса (решение Meta Class), либо полностью игнорируют @staticmethod
/ @classmethod
декораторы, которые украшают метод класса / экземпляра (решение setattr
. Например, декоратор @staticmethod
игнорируется, и self
все еще передается этой функции в качестве первого аргумента.
Как это можно сделать в Python 2.7?
Например, следующий иностранный класс: SQLAlchemy от flask_sqlalchemy
. Конечным результатом будет то, что я смогу вызвать другую функцию перед выполнением запрошенного вызова функции.
Это моя неудачная попытка:
class WithWrapping(object):
def __init__(self, other_cls, *args, **kwargs):
self.other = other_cls(*args, **kwargs)
self.other_cls = other_cls
def __getattr__(self, attr):
other_attr = self.other.__getattribute__(attr)
if callable(other_attr):
other_attr = getattr(self.other_cls, attr, None)
if not other_attr:
other_attr = getattr(self.other, attr, None)
def wrapper(*args, **kwargs):
# Do something here prior to function call
r = other_attr(*args, **kwargs)
if r == self.other:
return self
return r
return wrapper
else:
return other_attr
Этоне будет работать, если вы запустите следующее:
from flask_sqlalchemy import SQLAlchemy
db = WithWrapping(SQLAlchemy)
class Foo(db.TypeDecorator):
pass
То, что вы получите:
TypeError Traceback (most recent call last)
<ipython-input-4-9813b186f710> in <module>()
1 from flask_sqlalchemy import SQLAlchemy
2 db = WithWrapping(SQLAlchemy)
----> 3 class Foo(db.TypeDecorator):
4 pass
TypeError: Error when calling the metaclass bases
function() argument 1 must be code, not str
Что я пытался отладить, но довольно сложно следить за многими внутренними вызовами там.