Python 访问注入对象';什么是包含对象?
给定一个包含可调用对象B的对象A,是否有办法从Python 访问注入对象';什么是包含对象?,python,code-injection,Python,Code Injection,给定一个包含可调用对象B的对象A,是否有办法从B内部确定“A”。\uuuu call\uuu() 这是用于测试注入,其中A.B最初是一种方法 代码如下所示: # Class to be tested. class Outer(object): def __init__(self, arg): self.arg = arg def func(self, *args, **kwargs): print ('Outer self: %r' % (self,)) # Frame
B内部确定“A”。\uuuu call\uuu()
这是用于测试注入,其中A.B最初是一种方法
代码如下所示:
# Class to be tested.
class Outer(object):
def __init__(self, arg):
self.arg = arg
def func(self, *args, **kwargs):
print ('Outer self: %r' % (self,))
# Framework-provided:
class Injected(object):
def __init__(self):
self._replay = False
self._calls = []
def replay(self):
self._replay = True
self._calls.reverse()
def __call__(self, *args, **kwargs):
if not self._replay:
expected = (args[0], args[1:], kwargs)
self._calls.append(expected)
else:
expected_s, expected_a, expected_k = self._calls.pop()
ok = True
# verify args, similar for expected_k == kwargs
ok = reduce(lambda x, comp: x and comp[0](comp[1]),
zip(expected_a, args),
ok)
# what to do for expected_s == self?
# ok = ok and expected_s(this) ### <= need "this". ###
if not ok:
raise Exception('Expectations not matched.')
# Inject:
setattr(Outer, 'func', Injected())
# Set expectations:
# - One object, initialised with "3", must pass "here" as 2nd arg.
# - One object, initialised with "4", must pass "whatever" as 1st arg.
Outer.func(lambda x: x.arg == 3, lambda x: True, lambda x: x=='here')
Outer.func(lambda x: x.arg == 4, lambda x: x=='whatever', lambda x: True)
Outer.func.replay()
# Invoke other code, which ends up doing:
o = Outer(3)
p = Outer(5)
o.func('something', 'here')
p.func('whatever', 'next') # <- This should fail, 5 != 4
待测试的类。
类外部(对象):
定义初始化(self,arg):
self.arg=arg
def func(自身、*args、**kwargs):
打印('外部自我:%r'(自我,))
#提供的框架:
类注入(对象):
定义初始化(自):
self.\u replay=False
self.\u calls=[]
def重播(自我):
self.\u replay=True
self.\u calls.reverse()
定义调用(self,*args,**kwargs):
如果不是自己,请重播:
预期=(参数[0],参数[1:],kwargs)
self.\u calls.append(应为)
其他:
expected_s,expected_a,expected_k=self.\u calls.pop()
ok=正确
#验证args,与预期的_k==kwargs类似
确定=减少(λx,comp:x和comp[0](comp[1]),
zip(预期为a,args),
(好的)
#如何处理预期的_s==self?
#ok=ok和预期的(这个)#
给定一个对象A,其中包含
可调用对象B,有没有办法
从内部确定“A”
B.呼叫()
不是在一般情况下,也就是说,具有本文所要求的无限一般性——除非B
以某种方式保留对a
的引用,否则Python肯定不会代表B
保留它
对于您的预期用例来说,情况更糟:即使B
本身保留了对a
的引用(就像方法对象对其类的引用一样),它也不会有帮助,因为您在B
上到处践踏B
,而无需求助于setattr
,这相当于一个赋值。类Outer
中没有留下痕迹,在快乐的年代,它有一个func
属性,具有某些特征:该属性不再存在,被您的setattr
删除
这不是真正的依赖注入(一种需要注入对象的合作的设计模式),它是monkey patching,我最讨厌的事情之一,它的破坏性、不可恢复性(你目前正在挣扎)是我为什么对它感到恼火的部分原因。也许你想要?你是对的,它不是依赖注入,它突然断了。不管怎样,这似乎和我担心的一样困难。我需要替换该方法,并且需要替换
\uuuu init\uuu
以在实例化时再次替换该方法,这次使用代理方法,该方法将包含的对象传递给B
。。。可行,但不可维护,所以最好留作实验。