我如何覆盖python中嵌入的函数/定义值

时间:2012-02-24 01:43:38

标签: python

如果我的问题中的术语不正确,我会提前道歉。我想知道是否有可能覆盖隐藏在一堆连续Class调用中的变量,这些变量也没有直接访问权限,但仍会影响结果。

这是我试图写的一个例子,希望能让我的问题更清楚。

我有3个python模块,test1.py,test2.py和test3.py。每个模块都有一个类和一些定义。 Test2.py是运行代码的地方。

Test1.py

class A(object):
    def __init__(self, value=5):
        self.a = value
    def foo(self, value3 = 7, value4 = 5):
        from test3 import D
        c = self.a + value3 + value4
        d = D()
        e = d.B()
        f = c + e
        return f

class B(object):
    def __init__(self, value = 1):
        self.d = value
        object1 = A(self.d)
        self.fooReturn = object1.foo()
    def bar(self, value2 = 3):
        f = value2
        g = self.fooReturn + self.d + f
        return g

Test3.py

class D(object):
    def __init__(self, value=6, wanted_value=9):
        self.value = value + wanted_value
    def A(self, value3 = 4):
        self.value3 = value3 * 2
        return self.value3
    def B(self, value4 = 5):
        valuex = self.A()
        value5 = value4 + self.value + valuex
        return value5

Test2.py

from test1 import B

if __name__ == '__main__':
    test = B(4)
    result = test.bar()
    print result

返回值: -

55

我很抱歉看起来很复杂,这是我试图让价值看起来超出正常范围的方式:)

基本上我想要做的是找出如何在Test3.py,D类, init def中重新定义'wanted_value'的值,同时不更改Test2中的'if'的.py。

if __name__ == '__main__':
    test = B(4)
    result = test.bar()
    print result

我可以看到的一种方法是重新定义Test2.py中的D类定义,并使用全局变量将对原始类D的任何调用重定向到修改后的类。

e.g。

Test2.py

from test1 import B
from test3 import D

class Dx(D):
    # add the value I want to use to 'wanted_value'
    def __init__(self, value=6, wanted_value=3):
        self.value = value + wanted_value

# create a global
D.__init__ = Dx.__init__

if __name__ == '__main__':
    test = B(4)
    result = test.bar()
    print result

这个错误说'unbound method_ init _()必须用Dx实例作为第一个争论来调用。

所以这显然是不正确的,但如果这是一种让它无需重新定义整个D类的方法吗?

任何帮助都会很棒。很明显,我对继承的了解不是太热了:))

感谢。

2 个答案:

答案 0 :(得分:2)

通常无能执行此操作被视为一项功能。将问题分离到不同的模块/类中的重点是将实现分离,以便对代码的一部分进行小的更改,而不是在其他地方打破其他内容的效果。

您的Test2.py仅使用课程B。在理想的世界中,它不应该关心该类的实现。如果B以这样的方式实现,即它对D的依赖不属于B的接口(即没有参数或类型为D的返回值,也不会让任何参数让B的用户控制D的初始化,那么使用B的代码不应该依赖B的事实}在内部使用D。通过更改B来调整您从D获得的行为会将您与B的此特定实现相结合,并且作为副作用将打破期望D的任何其他用途{1}}具有通常的默认值。

在模块范围内执行此操作尤其不利,因为使用wanted_value的其他不相关模块将受到对类D的更改的影响,具体取决于您的模块是否已导入,这可能发生在该计划完全不相关的部分。


所以这些都是你通常不应该这样做的原因。假设你已经考虑过这个以及是否有其他方法来获得你想要的东西并决定它真正是你想要的,无论如何你都是这样做的。 :)

你实际上是在正确的轨道上。问题是您在课程D上定义了__init__,然后尝试将其转移到Dx。但是当你执行D时,你没有获得函数对象,你会得到一个“未绑定的方法”(在Python 2.x中;这个概念已经从Python 3中消失了)。 “未绑定方法”几乎与函数完全相同,但它检查其第一个参数(通常为Dx.__init__)实际上是您从中检索它的类的实例。由于self的{​​{1}}方法将在D的实例上调用,而不是从(__init__)检索D的类的实例,不会起作用。

但是没有必要把它放在课堂上。您可以Dx.__init__,然后分配Dx

另一种解决方法,如果只是更改方法的默认参数,则直接获取默认值。这是一个例子:

def __init__

无论你采用哪种方式,最好在创建特殊D.__init__ = __init__之前对class Foo(object): def __init__(self, apple='orange'): self.apple = apple f = Foo() print f.apple # orange Foo.__init__.im_func.func_defaults = ('octopus',) f = Foo() print f.apple # octopus 进行全局破解,然后在之后恢复它。可能你应该将它包装在一个函数中:

D

答案 1 :(得分:1)

可以访问深层隐藏的嵌套属性,但它容易出错。您应该考虑重新考虑您的模型。

根据经验:如果很难解释它可能是错误的方式。

这个嵌套结构似乎没有理由,因为你只是重用其他对象中存储的值。

这就像你想要离开你的车,因此降低玻璃,从外面抓住门把手打开门,而不是使用内门把手。

基本上你想分享一些价值观。如果你真的想为它创​​建特殊的类 您可以想象的共享值:

class CommonValues(object):
    def __init__(self, **kwargs): self.__dict__ = kwargs
    def value_exists(self, name): return hasattr(self, name)
    def add_value(self, name, value): setattr(self, name, value)

对于实际计算,您可以使用和init-method创建一个抽象基类,它将CommonValues对象作为参数:

class CalcBase(object):
    def __init__(self, common_values): self.cvalues = common_values
    def calculate(self): pass

对于特定的计算,您可以继承:

class CalcA(CalcBase):
    def calculate(self):        
        return result if self.cvalues.b > 4 else self.cvalues.c

class CalcB(CalcBase):
    def calculate(self, coef):
        if not self.cvalues.value_exists('d'):
           self.cvalues.add_value('d', 4)   
        result = 4*2 + coef * self.cvalues.c * self.cvalues.d
        return result if self.cvalues.b > 4 else self.cvalues.c

现实世界的计算就像:

cv = CommonValues(a=1, b=2, c=3, d=4)

resulta = CalcA(cv).calculate()
resultb = CalcB(cv).calculate(3)

cv.c = resulta + resultb
resultc = CalcB(cv).calculate(12.5)

而不是:

     depends
 >-----------v
 |           |
 A <-- B <-- C
 ^     |
 |     v
 | <-- D

考虑:

A -->|
B -->|__> F
C -->| 
D -->|

哪个图表似乎更容易理解,更不容易出错? ;-)