Tôi đã viết một số trình bao bọc có một đối tượng khác làm thuộc tính. Trình bao bọc này (chuyển tiếp) tất cả các yêu cầu thuộc tính với __getattr__
và __setattr__
đối tượng được lưu trữ làm thuộc tính. Tôi cần những gì khác để cung cấp cho proxy của mình để trình bao bọc trông giống như lớp bọc trong các trường hợp thông thường?Cách giả mạo/proxy một lớp trong Python
Tôi cho rằng tôi cần sửa những thứ như kế thừa, có thể __repr__
, ... Tôi cần phải xử lý những gì khác và cách khắc phục thừa kế để instanceof()
hoạt động?
EDIT: nỗ lực của tôi để thực hiện một chức năng proxy, tuy nhiên như tôi không hiểu được công thức hoàn toàn, nó không thành công :(
setattr_=object.__setattr__
getattr_=object.__getattribute__
class Proxy(object):
__slots__=["_func", "_params", "_kwargs", "_obj", "_loaded", "__weakref__"]
def __init__(self, func, *params, **kwargs):
setattr_(self, "_func", func)
setattr_(self, "_params", params)
setattr_(self, "_kwargs", kwargs)
setattr_(self, "_obj", None)
setattr_(self, "_loaded", False)
def _get_obj(self):
if getattr_(self, "_loaded")==False:
print("Loading")
setattr_(self, "_obj", getattr_(self, "_func")(*getattr_(self, "_params"), **getattr_(self, "_kwargs")))
setattr_(self, "_loaded", True)
return getattr_(self, "_obj")
#
# proxying (special cases)
#
def __getattribute__(self, name):
return getattr(getattr_(self, "_get_obj")(), name)
def __delattr__(self, name):
delattr(getattr_(self, "_get_obj")(), name)
def __setattr__(self, name, value):
setattr(getattr_(self, "_get_obj")(), name, value)
def __nonzero__(self):
return bool(getattr_(self, "_get_obj")())
def __str__(self):
return str(getattr_(self, "_get_obj")())
def __repr__(self):
return repr(getattr_(self, "_get_obj")())
#
# factories
#
_special_names=[
'__abs__', '__add__', '__and__', '__call__', '__cmp__', '__coerce__',
'__contains__', '__delitem__', '__delslice__', '__div__', '__divmod__',
'__eq__', '__float__', '__floordiv__', '__ge__', '__getitem__',
'__getslice__', '__gt__', '__hash__', '__hex__', '__iadd__', '__iand__',
'__idiv__', '__idivmod__', '__ifloordiv__', '__ilshift__', '__imod__',
'__imul__', '__int__', '__invert__', '__ior__', '__ipow__', '__irshift__',
'__isub__', '__iter__', '__itruediv__', '__ixor__', '__le__', '__len__',
'__long__', '__lshift__', '__lt__', '__mod__', '__mul__', '__ne__',
'__neg__', '__oct__', '__or__', '__pos__', '__pow__', '__radd__',
'__rand__', '__rdiv__', '__rdivmod__', '__reduce__', '__reduce_ex__',
'__repr__', '__reversed__', '__rfloorfiv__', '__rlshift__', '__rmod__',
'__rmul__', '__ror__', '__rpow__', '__rrshift__', '__rshift__', '__rsub__',
'__rtruediv__', '__rxor__', '__setitem__', '__setslice__', '__sub__',
'__truediv__', '__xor__', 'next',
]
@classmethod
def _create_class_proxy(cls, theclass):
"""creates a proxy for the given class"""
def make_method(name):
def method(self, *args, **kw):
return getattr(getattr_(self, "_get_obj")(), name)(*args, **kw)
return method
namespace={}
for name in cls._special_names:
if hasattr(theclass, name):
namespace[name]=make_method(name)
return type("%s(%s)"%(cls.__name__, theclass.__name__), (cls,), namespace)
def __new__(cls, obj, *args, **kwargs):
"""
creates an proxy instance referencing `obj`. (obj, *args, **kwargs) are
passed to this class' __init__, so deriving classes can define an
__init__ method of their own.
note: _class_proxy_cache is unique per deriving class (each deriving
class must hold its own cache)
"""
try:
cache=cls.__dict__["_class_proxy_cache"]
except KeyError:
cls._class_proxy_cache=cache={}
try:
theclass=cache[obj.__class__]
except KeyError:
cache[obj.__class__]=theclass=cls._create_class_proxy(obj.__class__)
ins=object.__new__(theclass)
theclass.__init__(ins, obj, *args, **kwargs)
return ins
if __name__=='__main__':
def t(x, y):
print("Running t")
return x+y
a=Proxy(t, "a", "b")
print("Go")
print(a+"c")
Không quan tâm, tại sao bạn không kế thừa? – brice
Bởi vì wrapper này là nghĩa vụ phải bọc tất cả các loại đối tượng. Nó là một proxy tổng quát. – Gerenuk
Bạn đã thay đổi công thức một chút. Nó trông giống như những gì bạn thực sự muốn là 'functools.partial', nhưng có lẽ không; vấn đề bạn đang thực sự cố gắng giải quyết là gì? – SingleNegationElimination