【问题标题】:How to make sure a python function has no dependence on external variables?如何确保python函数不依赖外部变量?
【发布时间】:2015-03-09 17:27:07
【问题描述】:

假设我定义了一个函数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 有纯子程序和函数,但程序员用它来“承诺”子程序/函数不会修改任何外部变量,而子程序/函数仍然可以从中取值。

【问题讨论】:

  • 好吧,总是有快速而肮脏的方式

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


【解决方案1】:

虽然有点老套,但您可以执行以下操作来检查函数代码对象中使用的指令:

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

【讨论】:

    【解决方案2】:

    首先,您可以像“如何检查我的函数是否纯”一样提出问题。

    答案 - 在 python 中是不可能的。别看。此外,如果您想检查代码的纯度,最好使用另一种语言。

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-11-16
        • 2019-08-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-08-24
        • 2012-06-16
        相关资源
        最近更新 更多