原始类型的python call-by-reference

1 python pass-by-reference primitive-types

我有使用命令式语言(最常见的C)的经验,这可能是我在学习python时感到困惑的原因.

我试图实现一个简单的按位标志设置函数.所以在C中它会是这样的:

void set_state(int *state, int var, int set)
{
    (set)? *state |= var : *state &= ~var
}

int is_state(int *state, int var)
{
    return (*state & var > 0)
}
Run Code Online (Sandbox Code Playgroud)

int*state指的是我跟踪的状态标志,var是我想设置或清除的标志(由int set决定).

所以我尝试用Python 3.2做同样的事情......

def setState(nState, nVar, bSet):
    if bSet:
        nState |= nVar
    else:
        nState &= ~var
    print(nState)
Run Code Online (Sandbox Code Playgroud)

然后我跑了......

>>> state
1024
>>> nfirst
1
>>> nsecond
2
>>> setState(state, nfirst, True)
1025
>>> state
1024
Run Code Online (Sandbox Code Playgroud)

调试器告诉我'state'的值被复制到nState中,现在nState自身发生了变异(意味着它在自己的本地范围内被改变了).是不是python都是关于对象和一切 - 是通过引用调用?

如果是这样,为什么我不能看到副作用?

我搞不清楚了.有人可以解释这里发生了什么.

Joh*_*ooy 8

Python int是不可变的,因此在传入引用时,无法更改int对象的值.如您所见,局部变量是引用的副本,因此它们都绑定到同一个整数.但是,当您更改局部变量的值时,将创建一个新的整数对象,并且局部变量将反弹到新对象.

例如.

>>> def setState(nState, nVar, bSet):
...     print((nState, id(nState)))
...     if bSet:
...         nState |= nVar
...     else:
...         nState &= ~var
...     print((nState, id(nState)))
... 
>>> nState = 1024
>>> nState, id(nState)
(1024, 3077840368)
>>> setState(nState, 1, True)
(1024, 3077840368)          # local nState is bound to the same object
(1025, 3077840448)          # now the local nState is bound to the new `int` object
Run Code Online (Sandbox Code Playgroud)

也许你可以从函数返回nState并将其分配回来,例如

>>> def setState(nState, nVar, bSet):
...     if bSet:
...         nState |= nVar
...     else:
...         nState &= ~var
...     return nState
... 
>>> nState = 1024
>>> nState = setState(nState, 1, True)
>>> nState
1025
Run Code Online (Sandbox Code Playgroud)


Wla*_*ant 5

数字或字符串等基本类型是不可变的,即使数字是通过引用传递的,您也无法更改它。当您更改值时,您实际上创建了一个数字并将对其的引用分配给nState变量。