5

这是我在这里的第一篇文章,所以如果我做错了,请告诉我。我尝试寻找现有的答案,但不确定要搜索什么。

考虑以下简单示例,一个名为的 python 模块mymath.py仅使用内置的 python 操作和模块。这个自定义模块是可移植的,因此任何人都可以执行代码,而无需安装除了股票 python 之外的任何东西。

# mymath.py
import sys

def minus(a, b):
    return a-b

def mult(a, b):
    return a*b

def div(a, b):
    return a/b

def plus(a, b):
    return a+b

def sum_series(int_list):
    sum = 0
    for i in int_list:
        sum = plus(sum, i)
    return sum

def main():
    my_list = [2, 4, 6]
    value = sum_series(my_list)
    sys.stdout.write("your list total = {}".format(value))

请注意,main()只有 callsum_series()反过来调用plus(). 在这个虚构的代码库的其他地方可能需要其他函数,但我们只关心main().

现在,我只想将相关的源代码作为文本字符串复制到另一个对象。换句话说,收集main()及其所有依赖项(递归),产生一串可执行代码。

我目前的解决方案:

import inspect
import mymath
# copy the source code in to the callback
source = inspect.getsource(mymath)
# then append a call to the main function
source += "\nmain()"

这是可行的,将模块的本地副本作为字符串生成,main()无需导入mymath. 问题是knob现在所有额外未使用的功能都变得臃肿,尽管它能够mymath.py通过重新运行我当前的解决方案来获取我所做的任何更改。

所以,问题是 - 有没有办法做相当于:

source = getFunctionSourcerRecursively(mymath.main)  
source += "\nmain()"

导致源 =

# mymath.py 
import sys  

def plus(a, b):  
    return a+b  

def sum_series(int_list):  
    sum = 0  
    for i in int_list:  
        sum = plus(sum, i)  
    return sum  

def main():  
    my_list = [2, 4, 6]  
    sys.stdout.write("your list total = {}".format(sum_series(my_list)))  

main()

所以,基本上“源代码”现在只包含相关代码并且是可移植的,不再需要人们在异地安装 mymath。

如果您好奇,我的真实案例涉及使用 The Foundry Nuke(合成应用程序),它有一个内部回调系统,可以在knob(属性)上触发回调事件时运行代码。我希望能够与异地客户共享这些保存的 Nuke 文件(.nk.nknc),而不需要他们修改他们的系统。

4

1 回答 1

0

您可以尝试informal interfaces(又名协议)。虽然协议在许多情况下都可以正常工作,但在某些情况下,非正式接口或duck typing一般情况下会引起混淆。例如,一个AdditionMultiplication两者都是mathFunc()。但即使它们实现相同的接口/协议,它们也不是一回事。抽象基类或 ABC 可以帮助解决这个问题。

ABC 背后的概念很简单——用户定义本质上是抽象的基类。我们将基类上的某些方法定义为抽象方法。因此,从这些基类派生的任何对象都被迫实现这些方法。由于我们使用的是基类,如果我们看到一个对象以我们的类作为基类,我们可以说这个对象实现了接口。那就是现在我们可以使用类型来判断一个对象是否实现了某个接口。

import mymath

class MathClass(mymath.ABC):
    @mymath.abstractmethod
    def mathFunc(self):
        pass
于 2017-11-27T15:08:50.517 回答