python:无意修改传递给函数的参数 [英] python: unintentionally modifying parameters passed into a function

查看:102
本文介绍了python:无意修改传递给函数的参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

几次,我不小心将输入修改为一个函数。由于Python没有常量引用,所以我想知道什么编码技术可以帮助我避免经常犯此错误?

A few times I accidentally modified the input to a function. Since Python has no constant references, I'm wondering what coding techniques might help me avoid making this mistake too often?

示例:

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)

当然,解决方法是在更改参数之前先对其进行复制:

Of course the fix is to make a copy of the parameter before I change it:

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

相比,副本更安全且更通用。容易忘记。

But it's so easy to forget.

我半想着要在每个函数的开头复制每个参数,除非该参数可能引用了一个大数据集。复制费用昂贵,或者除非打算修改自变量。这几乎可以解决问题,但是在每个函数开始时会导致大量无用的代码。此外,它实际上会覆盖Python的通过引用传递参数的方法,这大概是有原因的。

I'm half thinking to make a copy of each argument at the beginning of every function, unless the argument potentially refers to a large data set which may be expensive to copy or unless the argument is intended to be modified. That would nearly eliminate the problem, but it would result in a significant amount of useless code at the start of each function. In addition, it would essentially override Python's approach of passing parameters by reference, which presumably was done for a reason.

推荐答案

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

所以不要修改传入的字典,

So don't modify your incoming dictionary, create a new dictionary with a subset of the keys.

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

这种方法通常略效率更高,然后无论如何都要删除并删除不良元素。一般来说,通常更容易避免修改对象,而是创建新对象。

Such methods are typically slightly more efficient then going through and deleting the bad elements anyways. More generally, its often easier to avoid modifying objects and instead create new ones.

第二条一般规则: 不要修改容器在将它们传递出去之后。

通常不能假定已将数据传递到的容器已创建了自己的副本。因此,请勿尝试修改您给它们提供的容器。在交出数据之前,应进行任何修改。将容器传递给其他人后,您将不再是该容器的唯一主人。

You can't generally assume that containers to which you have passed data have made their own copies. As result, don't try to modify the containers you've given them. Any modifications should be done before handing off the data. Once you've passed the container to somebody else you are no longer the sole master of it.

第三条一般规则: don

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

If you get passed some sort of container, you do not know who else might be using the container. So don't modify it. Either use the unmodified version or invoke rule1, creating a new container with the desired changes.

第四条通用规则:(从Ethan Furman窃取)

Fourth general rule: (stolen from Ethan Furman)

某些功能需要修改列表。那是他们的工作。如果是这种情况,请在函数名中使其明显(例如列表方法追加和扩展)。

Some functions are supposed to modify the list. That is their job. If this is the case make that apparent in the function name (such as the list methods append and extend).

将其放入全部在一起:

只有一段代码可以访问该容器,它才应该修改该容器。

这篇关于python:无意修改传递给函数的参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆