Python 中的调用是如何工作的? [复制]

2024-03-19

对于我正在开发的一个项目,我正在实现一个链表数据结构,它基于对的概念,我将其定义为:

class Pair:
    def __init__(self, name, prefs, score):
        self.name = name
        self.score = score
        self.preferences = prefs
        self.next_pair = 0
        self.prev_pair = 0

where self.next_pair and self.prev_pair分别是指向上一个和下一个链接的指针。

为了设置链接列表,我有一个如下所示的安装函数。

def install(i, pair):
    flag = 0
    try:
        old_pair = pair_array[i]
        while old_pair.next_pair != 0:
            if old_pair == pair:
                #if pair in remainders: remainders.remove(pair)
                return 0
            if old_pair.score < pair.score:
                flag = 1
                if old_pair.prev_pair == 0: # we are at the beginning
                    old_pair.prev_pair = pair
                    pair.next_pair = old_pair
                    pair_array[i] = pair
                    break
                else: # we are not at the beginning
                    pair.prev_pair = old_pair.prev_pair
                    pair.next_pair = old_pair
                    old_pair.prev_pair = pair
                    pair.prev_pair.next_pair = pair
                    break
            else:
                old_pair = old_pair.next_pair
        if flag==0:
            if old_pair == pair:
                #if pair in remainders: remainders.remove(pair)
                return 0
            if old_pair.score < pair.score:
                if old_pair.prev_pair==0:
                    old_pair.prev_pair = pair
                    pair.next_pair = old_pair
                    pair_array[i] = pair
                else:
                    pair.prev_pair = old_pair.prev_pair
                    pair.next_pair = old_pair
                    old_pair.prev_pair = pair
                    pair.prev_pair.next_pair = pair
            else:
                old_pair.next_pair = pair
                pair.prev_pair = old_pair
        except KeyError:
            pair_array[i] = pair
            pair.prev_pair = 0
            pair.next_pair = 0

在该程序的过程中,我正在建立这些链接列表的字典,并从其中一些链接中删除链接并将它们添加到其他链接列表中。在修剪和重新安装之间,链接存储在中间数组中。

在调试这个程序的过程中,我逐渐意识到我对 Python 将参数传递给函数的方式的理解是有缺陷的。考虑我写的这个测试用例:

def test_install():
    p = Pair(20000, [3, 1, 2, 50], 45)
    print p.next_pair
    print p.prev_pair
    parse_and_get(g)
    first_run()
    rat = len(juggler_array)/len(circuit_array)
    pref_size = get_pref_size()
    print pref_size
    print install(3, p)
    print p.next_pair.name
    print p.prev_pair             

当我运行此测试时,我得到以下结果。

0
0
10
None
10108
0

我不明白的是为什么第二次打电话p.next_pair产生不同的结果(10108)比第一次调用(0). install不返回Pair可以覆盖传入的对象(它返回None),这并不是说我正在通过install一个指针。

我对按值调用的理解是解释器复制传递到函数中的值,使调用者的变量保持不变。例如,如果我说

def foo(x):
     x = x+1
     return x

baz = 2
y = foo(baz)
print y
print baz

Then 3 and 2应分别打印。事实上,当我在 Python 解释器中测试它时,结果就是这样。

如果有人能在这里指出正确的方向,我将非常感激。


在Python中,一切都是对象。简单的分配存储参考到指定对象名称中的指定对象。因此,将 Python 变量视为分配给对象的名称,而不是存储在命名位置的对象,会更直接。

例如:

baz = 2

... 商店位于baz指向整数对象的指针或引用2存储在其他地方。 (由于类型int是不可变的,Python 实际上有一个小整数池并重用相同的2对象无处不在,但这是一个实现细节,我们不需要太关心。)

你打电话时foo(baz), foo()的局部变量x也指向整数对象2首先。那就是foo()-本地名称x和全局名称baz是同一对象的名称,2. Then x = x + 1被执行。这改变了x指向不同的对象:3.

重要的是要理解:x不是一个可以容纳的盒子2, and 2然后增加到3. No, x最初指向2然后该指针更改为指向3。当然,既然我们没有改变什么对象baz指向,它仍然指向2.

另一种解释方式是,在 Python 中,所有参数传递都是按值传递的,但所有值都是对对象的引用。

与直觉相反的结果是,如果一个对象是可变的,则可以通过任何引用对其进行修改,并且所有引用都将“看到”更改。例如,考虑一下:

baz = [1, 2, 3]

def foo(x):
   x[0] = x[0] + 1

foo(baz)
print baz
>>> [2, 2, 3]

This seems与我们的第一个例子非常不同。但实际上,争论是通过同样的方式进行的。foo()接收到一个指向baz以...之名x然后对其执行操作以更改它(在这种情况下,列表的第一个元素指向不同的int目的)。区别在于名字x永远不会指向一个新对象;这是x[0]被修改为指向不同的对象。x本身仍然指向同一个对象baz。 (事实上​​,在幕后分配给x[0]变成方法调用:x.__setitem__()。) 所以baz“看到”列表的修改。怎么可能不呢?

对于整数和字符串,您不会看到这种行为,因为您无法更改整数或字符串;它们是不可变类型,当您修改它们时(例如x = x + 1)您实际上并没有修改它们,而是将变量名称绑定到完全不同的对象。如果你改变baz到一个元组,例如baz = (1, 2, 3),你会发现foo()给你一个错误,因为你不能分配给元组的元素;元组是另一种不可变类型。 “更改”元组需要创建一个新元组,然后赋值将变量指向新对象。

您定义的类的对象是可变的,因此您的Pair实例可以通过传入它的任何函数进行修改——也就是说,可以添加、删除属性或将属性重新分配给其他对象。这些都不会重新绑定任何指向您的对象的名称,因此当前指向它的所有名称都将“看到”更改。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Python 中的调用是如何工作的? [复制] 的相关文章

随机推荐

  • 如何将带有 formgroup 值的图像/文件上传到 API?

    当服务执行http post时 如何上传图像并将其添加到表单中 示例产品模块需要名称 价格 封面图片 我尝试使用许多可以从互联网 论坛等获得的方法 但对于这个问题仍然没有任何线索 我正在使用模型驱动的表单 并在选择图像时附加它 并且我尝试在
  • 正则表达式查找一行中最长的重复字符序列

    如何编写正则表达式来查找一行中最长的重复字符序列 通过正则表达式可以找到所有相关的字符序列 1 找到最长的此类序列最好使用正则表达式以外的工具来完成
  • SAPUI5 - Sap.m.RadioButton 值字段?

    sap m RadioButton已经只有Text属性并且没有Value属性 虽然我可以通过使用自定义数据来解决这个问题 但我是否遗漏了什么 sap ui commons RadioButton有一个key场地 另外 将值绑定到单选按钮组的
  • 为什么在 Java 中无法创建 MAX_INT 大小的数组?

    我读过这个问题的一些答案 为什么我无法创建大尺寸的数组 https stackoverflow com questions 31382531 why i cant create an array with large size and ht
  • 您如何知道用户在浏览器中输入的编码是什么?

    I read Joel 关于字符集的文章 http www joelonsoftware com articles Unicode html因此我采纳了他的建议 在我的网页和数据库中使用 UTF 8 我不明白的是如何处理用户输入 正如 Jo
  • JSF 页面未呈现为 HTML

    我正在尝试运行一个非常基本的 JSF 页面 使用 Websphere 7 0 作为服务器 因此我尝试坚持使用 JSF 1 2 浏览器不渲染 html 我的意思是它只是显示所有 html 代码 包括 doctype 等 我的第一个猜测可能是它
  • Codeigniter 分页链接转到 404 Page Not Found

    我有这个与搜索结果分页 http www andyhawthorne co uk how to paginate search results with codeigniter 实施到我的 CI 项目中 但是我无法让我的分页链接转到下一页
  • 什么时候适合使用CacheItemRemovedCallback?

    我有一个每天更新一次的大型数据集 我正在缓存对该数据进行昂贵查询的结果 但我想每天更新该缓存 我正在考虑使用 CacheItemRemovedCallback 每天重新加载我的缓存 但我有以下问题 是不是可以在我过期之前调用 CacheIt
  • Android 中的噪音消除是如何工作的?

    我碰到this http www talk3g co uk showthread php 7655 Google Nexus One Noise Cancellation Microphone win相对较旧的帖子 描述了 Nexus On
  • Django TestCase 测试顺序

    如果测试类中有多个方法 我发现执行顺序是按字母顺序排列的 但我想自定义执行顺序 如何定义执行顺序 例如 testTestA 将先于 testTestB 加载 class Test TestCase def setUp self def te
  • Python:在一行中拆分、剥离和连接

    我很好奇它们是否是某种蟒蛇魔法 我可能不知道能完成一些无聊的事情 给定行 csvData append join line split strip for x in L 我正在尝试分割一条线 修剪它周围的空白 然后加入 问题是 因为数组是从
  • 关于龙的可怕代码注释是什么?

    这句话被用来警告代码正在做一些严重的特技 我对此的谷歌搜索是空的 但我记得很久以前有人在谷歌上搜索过这个短语 谎言中的龙 龙睡在这里 Bah 这里是龙 http en wikipedia org wiki Here be dragons 最
  • 使用 google API、jQuery 从地理编码中提取 + 4 邮政编码

    我正在 jQuery 的帮助下使用谷歌 API 进行地理编码 以下是我尝试过的代码 jQuery document ready function var geocoder new google maps Geocoder jQuery Ad
  • 在“功能”选项卡上添加背景模式

    我使用的是 Xcode 6 3 我刚刚在功能选项卡上添加了蓝牙背景模式 需要执行一个步骤 即 将 所需的背景模式 键添加到您的 info plist 文件中 然而苹果文档 https developer apple com library
  • BeautifulSoup soup.prettify() 给出奇怪的输出

    我正在尝试解析一个网站 稍后我将在我的 Django 项目中使用它 为此 我使用 urllib2 和 BeautifulSoup4 然而 我却没能得到我想要的 BeautifulSoup 对象的输出很奇怪 我尝试了不同的页面 它有效 输出正
  • 在 Scala 2.10 中获取 java.lang.Class[T] 的 Scala 类型

    我在看scala 反射概述 http docs scala lang org overviews reflection overview html我想知道是否可以使用java lang Class
  • Python numpy 减法没有负数(4-6 给出 254)

    我想减去2gray人脸彼此之间可以看到差异 但我遇到了一个问题 例如减去 4 6 给出 254 而不是 2 或差值 2 print type face
  • 检查 JQuery 中的单选按钮

    我需要以编程方式检查单选按钮的值 该表格有一个id并且输入类型显然有一个名称 但没有 id 到目前为止 我成功运行的唯一代码是 input name my name eq 1 attr checked checked 但我希望能够通过明确提
  • 多个resque工作模式创建额外的进程

    我需要启动 4 个 resque 工作人员 所以我使用了以下命令 bundle exec rake environment resque workers RAILS ENV production COUNT 4 QUEUE VERBOSE
  • Python 中的调用是如何工作的? [复制]

    这个问题在这里已经有答案了 对于我正在开发的一个项目 我正在实现一个链表数据结构 它基于对的概念 我将其定义为 class Pair def init self name prefs score self name name self sc