使用这四个文件,所有文件都在同一目录中:
#imagine this is a third-party library
SPLIT_CHAR = ','
class Splitter(object):
def __init__(self, s, split_char=None):
self.orig = s
if not split_char:
self.splitted = s.split(SPLIT_CHAR)
#this person makes the mistake of re-setting the global variable
#in splitter to get different behavior, instead of just passing
#in the extra argument
import splitter
splitter.SPLIT_CHAR = '|'
def go():
s1 = splitter.Splitter("a|b|c|d")
print s1.orig
print s1.splitted
#this person expects the default behavior (splitting commas)
from splitter import Splitter
def go():
s1 = Splitter('a,b,c,d')
print s1.orig
print s1.splitted
import a
import b
a.go() #this one sets the global var in splitter
b.go() #this one expects the default behavior
experiment.py
的输出将为:
a|b|c|d
['a', 'b', 'c', 'd'] #okay... everything is fine
a,b,c,d
['a,b,c,d'] #not what the programmer expected.. should be split on commas
有没有办法阻止这个结果?在这种情况下,a.py
和b.py
可能是由两个不同的同事写的,但A的代码正在影响B.有时候覆盖模块中的某些东西很有用(例如monkeypatching),但在这种情况下它产生了令人困惑的行为。
是否有某种方法可以复制模块或沙箱执行,以便a.py
无法覆盖splitter.py
中的值并最终影响b.py
?
另外,让我们说代替简单的a.py
和b.py
,我们在mod_python下运行了一百个网络应用程序(尽可能地共享以减少内存),有没有办法防止一个流氓应用程序修改模块并打破所有其他应用程序?像Google App Engine这样的东西解决了,当然:)
答案 0 :(得分:2)
“有没有办法阻止这种结果?”
是。找到monkeypatched模块并让它们停止的人。
Monkeypatching不需要花哨的代码解决方法。它要求人们简单合作。
如果你写一个模块而某个同事弄得一团糟,你应该和那个同事谈谈。从长远来看,它更便宜,更简单,更有效。
答案 1 :(得分:1)
当你实例化Splitter
时,你将它的默认分裂字符设置为你想要的是什么,并为它设置一个setter,以便人们可以改变它?
答案 2 :(得分:1)
另一种防止这种情况的方法是通过调用它来提示“splint”.SPLIT_CHAR是“私有的”_SPLIT_CHAR。来自PEP8, the style guide for Python code:
_single_leading_underscore
:弱“内部使用”指标。例如。 “from M import *”不会导入名称以下划线开头的对象。
和
仅对非公共方法和实例变量使用一个前导下划线
所以虽然这些人都没有“不要惹我”,但这是对下一个用户的暗示,至少如果他们熟悉Python的风格。