python为什么对象之间会共享默认值?
小编:艳芬 882阅读 2020.08.25
这种类型的缺陷通常会惹恼新手程序员。考虑这个函数
def foo(mydict={}): # Danger: shared reference to one dict for all calls
... compute something ...
mydict[key] = value
return mydict
第一次调用此函数时,mydict 包含一项。第二次,mydict 包含两项,因为当 foo() 开始执行时, mydict 中已经有一项了。
函数调用经常被期望为默认值创建新的对象。 但实际情况并非如此。 默认值会在函数定义时一次性地创建。 如果对象发生改变,就如本示例中的字典那样,则对函数的后续调用将会引用这个被改变的对象。
按照定义,不可变对象例如数字、字符串、元组和 None 因为不可变所以是安全的。 对可变对象例如字典、列表和类实例的改变则可能造成迷惑。
由于这一特性,在编程中应遵循的一项好习惯是不使用可变对象作为默认值。 而应使用 None 作为默认值和函数中的值,检查值为 None 的形参并创建相应的列表、字典或其他可变对象。 例如,不要这样写:
def foo(mydict={}):
...
而要这样写:
def foo(mydict=None):
if mydict is None:
mydict = {} # create a new dict for local namespace
这一特性有时会很有用处。 当你有一个需要进行大量耗时计算的函数时,一个常见技巧是将每次调用函数的参数和结果值缓存起来,并在同样的值被再次请求时返回缓存的值。 这称为“记忆”,具体实现方式可以是这样的:
# Callers can only provide two parameters and optionally pass _cache by keyword
def expensive(arg1, arg2, *, _cache={}):
if (arg1, arg2) in _cache:
return _cache[(arg1, arg2)]
# Calculate the value
result = ... expensive computation ...
_cache[(arg1, arg2)] = result # Store result in the cache
return result
你也可以使用包含一个字典的全局变量而不使用参数默认值;这完全取决于个人偏好。
相关推荐
- Python 爬虫面试题 170 道:2019 版 所有题目 语言特性 1.谈谈对 Python 和其他语言的区别2.简述解释型和编译型编程语言3.Python 的解释器种类以及相关特点?4.说说你知道的Python3 和 Python2 之间的区别?5.Python3 和 Python2 中 int 和 long 区别?6.xrange 和 range 的区别?编码规范 7.什么…
- 自然语言处理工具python调用hanlp中文实体识别 Hanlp作为一款重要的中文分词工具,在GitHub的用户量已经非常之高,应该可以看得出来大家对于hanlp这款分词工具还是很认可的。本篇继续分享一篇关于hanlp的使用实例即Python调用hanlp进行中文实体识别。想要在python中调用hanlp进行中文实体识别,Ubuntu 16.04…
- 3DMAX提示和技巧 本主题标识使用 Civil View 的一些重要提示和技巧。常规使用屏幕分辨率至少为 1280x1024 的 Civil View。低于此分辨率时,一些面板将占用过多屏幕空间。 将视口设置为线框显示以达到最佳性能。 要尽可能简化用户界面,请在单个视口中工作并关闭 3ds Max 命令面…