gpt4 book ai didi

python - 如何在 Python 中伪造/代理一个类

转载 作者:IT老高 更新时间:2023-10-28 22:18:56 27 4
gpt4 key购买 nike

我写了一些包装器,它有另一个对象作为属性。此包装器将所有带有 __getattr____setattr__ 的属性请求代理(转发)到作为属性存储的对象。我还需要为我的代理提供什么,以使包装器在通常情况下看起来像被包装的类?

我想我需要修复继承之类的问题,也许是 __repr__,...我还需要注意什么以及如何修复继承以使 instanceof() 工作?

编辑:我尝试制作函数代理,但是由于我不完全理解配方,它失败了:(

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")

最佳答案

这个问题可以通过这个秘诀很好地解决:

Object Proxying (Python recipe)

您必须遵循的一般想法是,类上的大多数方法都是通过类本身或其元类上的 __getattr____getattribute__ 的某种组合来访问的,但这不适用于python特殊方法,以双下划线开头和结尾的方法,要找到的必须是实际类上的实际方法,不能进行属性代理。

您必须提供哪些方法显然取决于代理类本身提供的哪些方法。您需要为 isinstance() 提供的特殊方法是 __instancecheck__ and __subclasscheck__方法。要使 repr() 工作,您还必须在代理类本身上定义适当的 __repr__()

关于python - 如何在 Python 中伪造/代理一个类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9942536/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com