2017-11-11 77 views
3
所有的函數調用

我有一段代碼,看起來像這樣的工作:替換在Python

# This code is not modifiable 

from package import distance as dist 

class A: 
    def calculate(self): 
     ... 
     # call to dist() 
     ... 

我的代碼:

from package import A 

a = A() 
a.calculate() 

正如你所看到的,distance()功能在進口代碼的頂部。類A致電distance()函數。它是這樣做的,在幾個地方,不僅在calculate()

我想讓班級使用我的自定義距離功能。但是,該類不允許我在構造函數中傳遞它,並且我無法修改A的代碼。我將如何做到這一點?這可能通過子類化?我tryed以下,沒有工作:

from package import A 

class B(A): 
    def __init__(self): 
     from mypackage import mydistance as dist 
     return super().__init__() 

b = B() 
b.calculate() 
+0

把'package'的另一個版本在Python路徑更早?你可以改變'package'嗎? –

+0

@ Jean-FrançoisFabre不,我不能改變包裝。它來自於scipy https://docs.scipy.org/doc/scipy-0.15.1/reference/generated/scipy.spatial.distance.cdist.html – r0f1

+0

Python是一種動態語言,它的類,函數和可執行文件被存儲在查找字典中可以被訪問和修改。 試着做一些像'import package; package.dist = lambda x:10' 然後再次嘗試運行代碼,看看它是否已更新 – immortal

回答

1

可以使用mock.patch功能如下:

距離。PY:

def distance(): 
    print('distance called') 

mydistance.py:

def mydistance(): 
    print('mydistance called') 

a.py:

from distance import distance as dist 


class A: 
    def calculate(self): 
     dist() 

main.py:

from unittest import mock 

from a import A 
from mydistance import mydistance 


class B(A): 
    def calculate(self): 
     with mock.patch('a.dist', wraps=mydistance): 
      super().calculate() 


if __name__ == '__main__': 
    b = B() 
    b.calculate() 

輸出是:

mydistance called 

根據您的使用情況,您可能希望將with語句放在其他地方(例如在呼叫站點中)。例如:

if __name__ == '__main__': 
    b = B() 
    with mock.patch('a.dist', wraps=mydistance): 
     for _ in range(0, 100): 
      b.calculate() 

修補程序會導致一些開銷。另一個解決方案(如基本建議oetoni相同)是重新分配屬性(記得import a):

if __name__ == '__main__': 
    b = B() 
    old_dist = a.dist 
    a.dist = mydistance 
    for _ in range(0, 100): 
     b.calculate() 
    a.dist = old_dist 
0

你可以馬上做到這一點,從您的代碼,而不增加新的進口或在您引用使用mock.patch或任何第三類B.立即從yourcode一個

現在你只需要做你的小變化代碼,不只是做from package import A,但直接導入import baseA這樣我們控制它的所有變量也是進口;),因此我們可以。然後我們可以使用它的局部變量名,爲了趕它,改變它在運行時:d這樣:

在一個

distance.py的進口

應該距離()函數

def distance(something): 
    return something + 1 

那麼我想的名字baseA爲包含A類

baseA.py

文件
# This code is not modifiable 

from distance import distance as dist 


class A: 
    def calculate(self): 
     something = dist(1) 
     return something 

包含您運行的是進口的baseA

yourcode.py

import baseA 


def newDist(something): 
    return something + 2 


baseA.dist = newDist 
a = baseA.A() 


something = a.calculate() 
print(something) 

我成功的代碼,並從那裏,我們要修改的DIST(的地方)終於youcode文件設法改變baseA中dist的行爲,因此:) baseA.dist = newDist請記住不要放圓括號,因爲我們將該函數作爲對象傳遞,以便將其行爲分配給baseA.dist是從distance.py文件

進口的測試解決方案

enter image description here