python 对原始类型的引用调用

发布于 2024-11-17 06:13:50 字数 895 浏览 5 评论 0原文

我有使用命令式语言(最常见的是 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)
}

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

所以我尝试对 Python 3.2 做同样的事情,然后...

def setState(nState, nVar, bSet):
    if bSet:
        nState |= nVar
    else:
        nState &= ~var
    print(nState)

然后我运行...

>>> state
1024
>>> nfirst
1
>>> nsecond
2
>>> setState(state, nfirst, True)
1025
>>> state
1024

调试器告诉我“state”的值被复制到 nState 中,现在 nState 本身发生了变化(意味着它在自己的本地范围内发生了变化) )。难道Python不都是关于对象和一切都是按引用调用的吗?

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

我迷路了。有人可以解释一下这里发生了什么吗?

I have experience with the imperative languages(C most often), and that's probably why I am confused in learning python.

I am trying to implement a simple bitwise flag-setter functions. So in C it would be like:

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)
}

int *state refers to a state flag that I keep track of, and var is the flag that I would like to set or clear(decided by int set).

So I tried to do the same with Python 3.2 and...

def setState(nState, nVar, bSet):
    if bSet:
        nState |= nVar
    else:
        nState &= ~var
    print(nState)

Then I ran...

>>> state
1024
>>> nfirst
1
>>> nsecond
2
>>> setState(state, nfirst, True)
1025
>>> state
1024

debugger tells me that the value of 'state' got copied into nState and now nState got mutated itself(meaning it was changed in its own local scope). Wasn't python all about objects and everything-is-call-by-reference?

If so, why can't I see a side effect?

I am lost. Can someone explain what is going on here.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

橪书 2024-11-24 06:13:50

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

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

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

Python ints are immutable, so while a reference is being passed in, it is not possible to change the value of the int object. As you have seen, the local variable is a copy of the reference, so they are both bound to the same integer. However when you change the value of the local variable, a new integer object is created, and the local variable is rebound to the new object.

eg.

>>> 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

perhaps you can return nState from the function and assign it back, eg

>>> def setState(nState, nVar, bSet):
...     if bSet:
...         nState |= nVar
...     else:
...         nState &= ~var
...     return nState
... 
>>> nState = 1024
>>> nState = setState(nState, 1, True)
>>> nState
1025
寄与心 2024-11-24 06:13:50

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

Primitive types like numbers or strings aren't mutable, you cannot change a number even if it were passed by reference. When you changed the value you actually created a new number and assigned the reference to it to the nState variable.

酒浓于脸红 2024-11-24 06:13:50

http://mail.python.org/pipermail/tutor/2002-11月/018828.html 几乎回答了你的问题。

我们可以将Python中的所有“变量名”视为指向对象的指针。
事实上,这就是正在发生的事情。
[...]
这里的关键是 Python 中的算术(或对
“不可变”数据类型),但不会修改对象:它动态地
构造新对象:

由于列表、字典和自定义对象通常是可变的,对它们调用方法不会创建新对象,而是修改现有对象,因此您可以为您可能实际期望的类型提供按引用调用行为。

http://mail.python.org/pipermail/tutor/2002-November/018828.html pretty much answers your question.

We can think of all "variable names" in Python as pointers to objects.
In fact, that's pretty much what's going on.
[...]
The key here is that arithmetic in Python (or any manipulation on an
"immutable" data type), does not modify the object, though: it dynamically
constructs new objects:

Since lists, dicts and custom objects are usually mutable calling methods on them will not create a new object but modify the existing one, so you have the call-by-reference behaviour for those types you might actually expect.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文