python让我感到沮丧的一点是,如果我编写这样一个函数:
def UnintentionalValueChangeOfGlobal(a):
SomeDict['SomeKey'] = 100 + a
b = 0.5 * SomeDict['SomeKey']
return b
然后像这样运行:
SomeDict = {}
SomeDict['SomeKey'] = 0
b = UnintentionalValueChangeOfGlobal(10)
print(SomeDict['SomeKey'])
Python将:1)在函数调用期间查找并使用SomeDict
,即使我忘记将它作为函数的输入;2)永久更改SomeDict['SomeKey']
的值,即使它没有包含在函数的return语句中。你知道吗
对我来说,这常常会导致变量无意中更改值-SomeDict['SomeKey']
在这种情况下,在调用函数后变成110,而目的只是操纵函数输出b
。你知道吗
在本例中,我更希望python:1)在函数内部发生错误,说明SomeDict
未定义;2)在任何情况下,都不会在调用函数后永久更改除输出b
之外的任何变量的值。你知道吗
我知道在python中不能同时禁用globals,但是是否有一个简单的方法(模块或IDE等)可以对python函数执行静态分析,并在函数使用和/或更改非函数输出的变量值时向我发出警告?即,在使用或操作非函数本地变量时发出警告?你知道吗
可以使用globals()检查变量:
理想情况下,我希望我正在搜索的全局检查功能能够在IDE中实现,并持续用于评估函数中全局的使用情况。但由于这似乎不存在,我创建了一个特殊函数,它将python函数作为输入,然后查看该函数的字节码指令,以查看是否存在任何
LOAD_GLOBAL
或STORE_GLOBAL
指令。如果找到任何类型,它将尝试评估全局类型,并将其与用户提供的类型列表(int、float等)进行比较。然后打印出函数使用的所有全局变量的名称。你知道吗这个解决方案还远远不够完美,而且很容易出现误报。例如,如果在导入numpy(
import numpy as np
)之前在函数中使用np.unique(x)
,它将错误地将np
标识为全局变量而不是模块。它也不会研究嵌套函数等但是对于一些简单的例子,比如本文中的例子,它似乎工作得很好。我只是用它来扫描我的代码库中的所有函数,它发现了另一个我不知道的全局用法-所以至少对我来说它是有用的!你知道吗
函数如下:
当在声明函数之后直接在示例中的函数上使用时,它将发现有关全局变量
SomeDict
的用法的警告,但不会知道其类型:在定义
SomeDict
之后使用时,它还检测到全局是dict:注意:在当前状态下,函数无法检测到
SomeDict['SomeKey']
更改值。也就是说,它只检测加载指令,而不检测全局的前一个值是否被操纵。这是因为在本例中使用指令STORE_SUBSCR
而不是STORE_GLOBAL
。但是全局的使用仍然被检测到(因为它正在被加载),这对我来说已经足够了。你知道吗Python没有提供任何明显且简单的方法来阻止在函数中访问(未声明的)全局名称的原因之一是,在Python中,所有东西(至少可以分配给名称的所有东西)都是对象,包括函数、类和模块,因此阻止函数访问未声明的全局名称将有助于相当冗长的代码。。。嵌套作用域(闭包等)也没有帮助。你知道吗
当然,尽管globals是邪恶的,但有时仍然有合理的理由使一个global对象发生变异。FWIW,即使是过梁(至少是pylint和pyflakes)似乎也没有任何选择来检测这个AFAICT-但你必须自己仔细检查,因为我可能忽略了它,或者它可能作为pylint扩展或存在于另一个过梁中。你知道吗
奥托,我很少有错误来自这样的问题在20多年来(我不记得一个单一的发生实际上)。常规应用基本的良好实践——尽可能避免副作用的简短函数、有意义的名称和良好的命名约定等,至少对关键部分进行单元测试等——似乎足以有效地防止此类问题。你知道吗
这里的一个要点是,我有一个关于不可调用全局变量被视为(伪)常量的规则,它通过将它们全部命名为\u UPPER来表示。这使得它非常明显,当你真的变异或重新绑定一个。。。你知道吗
作为一个更一般的规则:Python本质上是一种非常动态的语言(见鬼,你甚至可以在运行时更改对象的类……),并且有一个“我们都是同意的成年人”的哲学,因此它确实“缺乏”了大多数安全保护,你可以在更多的“B&D”语言(如Java)中找到,而不是依赖于约定,良好的实践和常识。你知道吗
现在,Python不仅是动态的,而且还公开了它的许多内部内容,因此您当然可以(如果这还不存在的话)编写一个pylint extension,它至少可以检测函数代码中的全局名称(提示:您可以使用
yourfunc.co_code
(py2)或yourfunc.__code__
(py3)访问the compiled code of a function object,然后检查代码中使用的名称)。但是,除非你不得不面对一群草率、无纪律的开发人员(在这种情况下,你还有另一个问题——愚蠢没有技术解决方案),否则我非常谦虚的看法是你在浪费时间。你知道吗相关问题 更多 >
编程相关推荐