如何确保python函数不依赖于外部变量?

时间:2015-03-09 17:27:08

标签: python debugging syntax functional-programming functional-testing

假设我已经定义了一个函数f(x),这在语法上是正确的。我想确保f在功能上“有效”,因为它的输出完全取决于输入x

有时,如果f的定义很复杂,可能会无意中(因为输入错误,或者只是不够小心)在其定义中引用一些外部变量,这可能会导致很难发生的错误找出来。

是否有任何工具,任何“指示实用程序”(可以这么说),或任何“最佳实践”以确保不会发生这种情况?

示例:

xx = 1.0

def f(x, y, p=1):
    return xx * y**p # A typo here: should be x * y**p

如果没有简单的方法在python中实现这一点,哪些语言有这样的功能?据我所知,C,C ++和Fortran没有这个。 Fortran 95具有纯子程序和函数,但程序员使用它来“保证”子程序/函数不会修改任何外部变量,而子程序/函数仍然可以从中获取值。

3 个答案:

答案 0 :(得分:2)

虽然它有点hackish,你可以做这样的事情来检查函数代码对象中使用的指令:

import opcode  # see /Python/Lib/opcode.py

GLOBAL_INSTRUCTIONS = {opcode.opmap['DELETE_GLOBAL'],
                       opcode.opmap['LOAD_GLOBAL'],
                       opcode.opmap['STORE_GLOBAL']}

def is_pure(func):
    for inst in instructions(func.func_code.co_code):
        op = inst[0]
        if op in GLOBAL_INSTRUCTIONS:
            return False
    return True

def instructions(code):
    """Iterates over a code string yielding integer [op, arg] pairs
    """
    code = map(ord, code)
    i, L = 0, len(code)
    extended_arg = 0
    while i < L:
        op = code[i]
        i+= 1
        if op < opcode.HAVE_ARGUMENT:
            yield [op, None]
            continue
        oparg = code[i] + (code[i+1] << 8) + extended_arg
        extended_arg = 0
        i += 2
        if op == opcode.EXTENDED_ARG:
            extended_arg = oparg << 16
            continue
        yield [op, oparg]

xx = 1.0

def f(x, y, p=1):
    return xx * y**p # A typo here: should be x * y**p

def f2(x, y, p=1):
    return x * y**p # No typo

print(is_pure(f))   # --> False
print(is_pure(f2))  # --> True

答案 1 :(得分:1)

首先 - 你可以问你的问题&#34;如何检查我的功能是否纯净&#34;。

答案 - 在python中它是不可能的。不要看。此外,如果您想在代码中检查纯度,那么使用其他语言可能会更好。

答案 2 :(得分:1)

在python中通常不可能。如果您想要一种强制执行纯函数和参照透明度的语言,请尝试使用Haskell