区分只读函数输入参数和可变输入参数的 Pythonic 方法

Pythonic way to distinguish read-only function input parameters from mutable ones

Python 似乎没有每个 How do I create a constant in Python? 有效的 const 限定符什么是区分只读/可变函数参数的最“pythonic”方式?我应该在评论中指出吗?

# my_graph is READ-ONLY
# my_set is added items with property X ...
def my_lovely_function(my_graph,my_set):

在 C 和其他几种语言中,通常实际输出是通过通过指针或引用传递的输入进行通信的。这样做的原因是许多这些范例中的 return 值机制已被劫持用于错误处理目的,即 return 值是 success/error 代码,而有用的输出填充在 input/pointer参考。这导致需要将某些输入表示为不可触摸(常量),而将其他输入表示为可触摸以防止在使用该功能时出现混淆。

Python 通常不希望您那样做。它希望您使用异常和异常处理来进行错误处理,并使用 return 语句来进行实际输出。这更清晰,更符合 return 值在被错误处理劫持之前的原始想法。

在某些情况下,使用可变输入将数据传出仍然更方便。 python 中的所有内容始终通过引用。这很好,除非调用上下文不希望您(函数)修改它作为输入提供的变量。

Python 的解决方案是 1) 期望函数编写器正确记录输入、输出和对可变输入的副作用,以及 2) 为调用上下文提供传递不可变对象的选项如果他们想确保这些对象不会被更改。

因此,如果您有一个列表并且您不想调用某个函数来从中添加或减去内容,请将信息作为元组传递。没有函数能够向您的元组添加或减去任何内容,但是如果这些元素是可变的,它们可能能够更改元组的元素。传递一个 frozenset 而不是一个集合。没有不可变的 dict 类型,但您可以通过传递副本或将其转换为冻结的元组集来解决这个问题。字符串、整数、浮点数和复数都是不可变的。请注意,嵌入在不可变容器中的可变对象仍然可以更改。如果这是不需要的,那么请确保它们是不可变的。或者,如果您是偏执狂,则可以在对象上调用 copy.deepcopy() 以制作完全独立的副本(递归地)以传递给函数。此深层副本的任何嵌套级别的任何更改都不会影响原始对象。

在编写函数时,应该从文档(最好是文档字符串)或代码本身清楚 return 值和对可变对象的副作用是什么。在编写函数时使用文档字符串来捕获这一点是最佳实践。

在调用函数时,您应该根据具体情况使用不可变类型(或在需要时进行深度复制)来防御性使用。