Python 访问注入对象';什么是包含对象?

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,是否有办法从
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
。。。可行,但不可维护,所以最好留作实验。