python:无意中修改传递给函数的参数

标签 python coding-style

有几次我不小心修改了函数的输入。由于 Python 没有常量引用,我想知道哪些编码技术可以帮助我避免经常犯这种错误?

例子:

class Table:
  def __init__(self, fields, raw_data):
    # fields is a dictionary with field names as keys, and their types as value 
    # sometimes, we want to delete some of the elements 
    for field_name, data_type in fields.items():
      if some_condition(field_name, raw_data):
        del fields[field_name]
    # ...


# in another module

# fields is already initialized here to some dictionary
table1 = Table(fields, raw_data1) # fields is corrupted by Table's __init__
table2 = Table(fields, raw_data2)

当然,解决方法是在我更改参数之前复制该参数:

  def __init__(self, fields, raw_data):
    fields = copy.copy(fields)
    # but copy.copy is safer and more generally applicable than .copy 
    # ...

但是很容易忘记。

我有一半的想法是在每个函数的开头复制每个参数,除非该参数可能引用一个复制成本很高的大型数据集,或者除非要修改该参数。这几乎可以消除问题,但会导致在每个函数的开头出现大量无用的代码。此外,它基本上会覆盖 Python 通过引用传递参数的方法,这大概是出于某种原因。

最佳答案

第一条一般规则: 不要修改容器:创建新容器。

所以不要修改传入的字典,使用键的子集创建一个新字典。

self.fields = dict( key, value for key, value in fields.items()
                     if accept_key(key, data) )

这种方法通常比遍历并删除坏元素更有效。更一般地说,避免修改对象并创建新对象通常更容易。

第二条一般规则: 不要在假冒后修改容器。

您通常不能假设您向其传递数据的容器已经制作了它们自己的副本。因此,不要试图修改您提供给他们的容器。任何修改都应该在传递数据之前完成。一旦您将容器交给其他人,您就不再是它的唯一主人。

第三条一般规则: 不要修改不是您创建的容器。

如果您通过了某种容器,您将不知道还有谁在使用该容器。所以不要修改它。使用未修改的版本或调用规则 1,创建具有所需更改的新容器。

第四条一般规则:(从 Ethan Furman 那里偷来的)

有些函数应该修改列表。那是他们的工作。如果是这种情况,在函数名称中明确说明(例如列表方法追加和扩展)。

综合起来:

当一段代码是唯一可以访问该容器的代码时,它应该只修改该容器。

关于python:无意中修改传递给函数的参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7379991/

相关文章:

Java 约定 : use getters/setters WITHIN the class?

coding-style - 编码风格主要是为了可读性还是有其他因素?

python - Python 中的均方误差

python - Google 混合 OpenID+OAuth 登录不提示 OAuth 访问

python - [[]]*3 和 [[] for i in range(3)] 的区别

jsf - JSF 消息的不同 CSS 样式

python - matplotlib.pyplot.annotate 中箭头的控制角度

python - 使用 Python 创建复杂的 JSON,并根据条件创建一些嵌套数组

WPF UI 元素命名约定

objective-c - 在枚举上使用 NSString 常量的原因?