Python 如何使用参数生成函数?

Python 如何使用参数生成函数?,python,python-3.x,Python,Python 3.x,我开始做一个相当简单的棒球项目,遇到了一个关于函数的问题。我以前使用过带变量的函数,所以我不知道为什么这不起作用 home = 0 def basestate(base): if base is 0: base = 1 print(base) else: base = 0 basestate(home) print(home) Base将作为一个打印,但home不会。理想情况下,我想在1和0之间做一个简单的状态切换。这似乎是最简单

我开始做一个相当简单的棒球项目,遇到了一个关于函数的问题。我以前使用过带变量的函数,所以我不知道为什么这不起作用

home = 0
def basestate(base):
    if base is 0:
        base = 1
        print(base)
    else:
        base = 0
basestate(home)
print(home)
Base将作为一个打印,但home不会。理想情况下,我想在1和0之间做一个简单的状态切换。这似乎是最简单的方法,但我不是专家

谢谢你的帮助


Zach

解决此问题的最简单方法是从
basestate
返回一个值,并将返回的值分配给
home

home = 0
def basestate(base):
    if base == 0:
        return 1
    else:
        return 0

home = basestate(home)
print(home)
更新

得益于s16h,对
基本状态的定义更具python风格:

def basestate(base):
    return 1 if base == 0 else 0
理想情况下,我想在1和0之间做一个简单的状态切换

对二进制状态开关使用True/False如何

home = False

home = not home
print(home) # True

home = not home
print(home) # False again

在查看代码时,会出现两种不同的情况:

可变与不可变数据类型

如中所述:

某些对象的值可以更改。值可以更改的对象称为可变对象;其值在创建后不可更改的对象称为不可变对象。(包含对可变对象的引用的不可变容器对象的值可以在可变对象的值更改时更改;但是,容器仍然被认为是不可变的,因为它包含的对象集合无法更改。因此,不可变性与具有不可更改的值并不完全相同,它更微妙)物体的易变性由其类型决定;例如,数字、字符串和元组是不可变的,而字典和列表是可变的

因此,在
home=0
的情况下,
0
是一个数字,因此它是不可变的

通过分配

在Python中,几乎所有东西都是对象。在Python中我们通常称之为“变量”的是更恰当的名称。类似地,“赋值”实际上是名称与对象的绑定。每个绑定都有一个定义其可见性的范围,通常是名称来源的块。Jeff Knupp更深入地讨论了这一点,并在中提供了更多示例

代码中发生了什么…

因此,当您拥有
home=0
时,现在我们知道名称
home
指向不可变的数字
0
。当您调用
basestate(home)
时,本地名称
base
被分配给
b
指向的同一个对象;
0
。此时,
id(home)==id(b)
(在CPython中,是内存中对象的地址)。但是,当您说
base=1
(或
base=0
)时,由于数字(
int
,在本例中)是不可变的,因此将为名称
base
分配一个新的数字对象
1
。旧的
0
对象仍然由
home
引用,而不是由
base
引用。所以,现在
id(home)!=id(基本)
,因为它们不再指向内存中的同一位置

因此,您正在将
1
(或
0
)分配给
base
,一旦函数退出,
base
就不再在范围内,并且它没有改变任何其他内容,如
home
,因为数字是不可变的

那我该怎么办?

您需要返回所需的值并将其重新分配给
主页

home = 0

def basestate(base):
    return 1 if base == 0 else 0

basestate(home)
print(home)
p.S.不要使用
is
进行这种比较。通常,在比较值时使用
=
,在比较标识时使用
is
。在本例中,您正在比较值。但是如果我说
id(home)==id(base)
,我可以说
home就是base

p.p.S在小数字上使用
id()
实际上是非常巧妙的,因为当前的CPython实现为-5到256之间的所有整数保留了一个整数对象数组,当您在该范围内创建一个整数时,实际上只会返回对现有对象的引用


我希望这有帮助

您偶然发现了“按引用传递”和“按值传递”之间的区别。差异取决于语言。在通过引用传递参数的语言中,当函数返回时,对参数参数所做的更改将反映在参数中。在按值传递参数的语言中,参数的值被复制到函数中,从而有效地创建变量的本地副本。局部函数范围变量的更改不会反映在用作参数的原始变量中。显然,Python在处理原语时是按值传递的。也许您想阅读本文,您还应该使用
=
而不是
is
来测试相等性<代码>测试对象相等,而
=
测试值相等。更多信息,请点击这里:@Misha-Ah,这真的很有趣。感谢您的解释。@Misha,严格地说,Python不是按引用传递或按值传递。这是一项临时任务。而且,据我所知,“参数的值被复制到函数中,从而有效地创建变量的本地副本”对于Python来说并不准确。变量的更改仅在局部可见,这一事实与值的可变性/不变性有关。第一次传入参数时,局部变量和变量外部的原始变量都将指向内存中的同一位置。如果base==0,则返回1,如果base==0,则返回0,这可能更像python。是的,这肯定会清除问题。谢谢