Python 将赋值替换为函数的方法
我知道不可能为作为参数传递给函数的变量分配新值Python 将赋值替换为函数的方法,python,Python,我知道不可能为作为参数传递给函数的变量分配新值 >>> a = 1 >>> def foo(bar): ... bar = 2 ... >>> foo(a) >>> a 1 但是可以用方法修改它 >>> a = [1, 2] >>> def foo(bar): ... bar.append(3) ... >>> foo(a) >>> a
>>> a = 1
>>> def foo(bar):
... bar = 2
...
>>> foo(a)
>>> a
1
但是可以用方法修改它
>>> a = [1, 2]
>>> def foo(bar):
... bar.append(3)
...
>>> foo(a)
>>> a
[1, 2, 3]
但是有没有一种方法可以代替赋值(给变量一个全新的值)。让我的第一个例子起作用的东西:
>>> a = 1
>>> def foo(bar):
... bar.assign(2)
...
>>> foo(a)
>>> a
2
我找到的唯一选择是全局变量和设计自己的类
因此,我的问题是:
首先,python中的每一样东西都是对象(除了一些单例和实习生),并且每个对象都存在于范围中,包含全局、局部、内置和封闭范围。使用作用域的主要目的显然是保留一组遵循特定目标的命令和脚本 因此,通过让不同范围内的变量相互影响来破坏这种体系结构是不合理的 但是在Python中,它为我们提供了一些工具,使一些变量在上层scope1中可用,比如
global
语句
注意:关于第二个示例,请记住,在函数中更改可变对象可能会影响调用方,这是因为像列表这样的可变对象实际上是指向实际对象的指针的容器,当您更改一个指针时,它将影响主对象
1.python中范围从内部到外部的层次结构是:本地、封闭、全局、内置。被称为LEGB方式。
这是两个设计决策的结果。首先,Python中的函数和参数是相同的。也就是说,如果你有这样的电话
foo(a)
大致可以翻译为
bar = a
<function body, verbatim>
bar=a
这就是为什么不能像在C中那样只传递一个指向任何变量的指针。如果你想改变一个函数参数,它必须有一些可变的内部结构。这就是第二个设计决策的所在:Python中的整数是不可变的,其他类型包括其他类型的数字、字符串或元组。我不知道这一决定背后的最初动机,但我看到了两个主要优势:
- 更容易让人对代码进行推理(当您将整数传递给函数时,可以确保整数不会发生神奇的变化)
- 计算机更容易对代码进行推理(出于优化或静态分析的目的),因为许多函数参数只是数字或字符串
我个人的观点是,你应该尽可能避免函数改变它们的参数。至少,它们应该是方法,并对相应的对象进行变异。否则,代码就很容易出错,很难维护和测试。因此,我完全支持这种不变性,并尝试在任何地方使用不可变对象。如果您想在没有
global
或return
指令的情况下更改某个函数中变量的值,那么您可以在函数参数中传递其名称,并使用globals()
:
python中的一切都是对象,python中的对象是可变的,除非它们不是可变的。字符串、数字(int、float)等基本类型是不可变的,即
1
始终是1
,您永远无法使1成为其他类型
事实上,大多数所谓的面向对象语言都是这样的,更像是一种优化
正如您所说,您需要创建自己的对象来包装不可变的类型,以便改变新对象的内部结构。您甚至可以创建一个非常简单的类来实现这一点
class Mutatable:
def __init__(self, value):
self.value = value
def assign(self, value):
# in python you cannot overload the = (assignment) operator
self.value = value
现在从你的例子你可以说
>>> a = Mutatable(1)
>>> def foo(bar):
... bar.assign(2)
...
>>> foo(a)
>>> a.value
out: 2
正如其他一些海报所提到的一般编程建议。过度使用变异会导致很难调试的应用程序。返回值并引发异常的函数更易于测试和调试。另一种方法是从函数返回修改后的值并将该值赋给变量。有关python中可以执行的一些操作,请参阅。记住,孩子们,不要在家里尝试。这意味着如果可以更改每个对象的值,我可以将
2
分配给1
,这是胡说八道吗?(对于a=1
,如果我改变a
我改变1
,那就比“a
包含/值得1
”更“a
是1
”?
>>> a = Mutatable(1)
>>> def foo(bar):
... bar.assign(2)
...
>>> foo(a)
>>> a.value
out: 2