使用 __getitem__ 就地自定义对象解压不同行为 python 3.5 与 python 3.6

2023-12-25

后续问题这个问题 https://stackoverflow.com/questions/50375793/elegant-way-to-have-an-almost-copy-constructor-that-allows-to-update-some-member:我在 python 3.5 和 python 3.6 上运行了下面的代码 - 得到了非常不同的结果:

class Container:

    KEYS = ('a', 'b', 'c')

    def __init__(self, a=None, b=None, c=None):
        self.a = a
        self.b = b
        self.c = c

    def keys(self):
        return Container.KEYS

    def __getitem__(self, key):
        if key not in Container.KEYS:
            raise KeyError(key)
        return getattr(self, key)

    def __str__(self):
        # python 3.6
        # return f'{self.__class__.__name__}(a={self.a}, b={self.b}, c={self.c})'
        # python 3.5    
        return ('{self.__class__.__name__}(a={self.a}, b={self.b}, '
                'c={self.c})').format(self=self)

data0 = Container(a=1, b=2, c=3)
print(data0)

data3 = Container(**data0, b=7)
print(data3)

正如上一个问题所述,这引发了

类型错误:类型对象获得关键字参数“b”的多个值

在Python 3.6上。但在 python 3.5 上我得到了异常:

密钥错误:0

此外,如果我不加注KeyError但只需打印出key and return in __getitem__:

def __getitem__(self, key):
    if key not in Container.KEYS:
        # raise KeyError(key)
        print(key)
        return
    return getattr(self, key)

这将打印出int顺序0, 1, 2, 3, 4, ...。 (蟒蛇3.5)

所以我的问题是:

  • 版本之间发生了什么变化导致其行为如此不同?

  • 这些整数从哪里来?


UPDATE: 正如评论中提到的λuser https://stackoverflow.com/users/6541288/%ce%bbuser:实施__iter__将更改 python 3.5 上的行为以匹配 python 3.6 的行为:

def __iter__(self):
    return iter(Container.KEYS)

这实际上是解包自定义映射对象和创建调用者参数期间多个内部操作之间的复杂冲突。因此,如果您想彻底了解根本原因,我建议您查看源代码。不过,您可以查看以下一些提示和起点以了解更多详细信息。

在内部,当您在调用者级别解包时,字节码BUILD_MAP_UNPACK_WITH_CALL(count) https://docs.python.org/3/library/dis.html#opcode-BUILD_MAP_UNPACK_WITH_CALL pops count来自堆栈的映射,将它们合并到一个字典中并推送结果。另一方面,带有参数的操作码的堆栈效果oparg 定义如下 https://github.com/python/cpython/blob/64fddc423fcbe90b8088446c63385ec0aaf3077c/Python/compile.c#L1003:

case BUILD_MAP_UNPACK_WITH_CALL:
    return 1 - oparg;

话虽如此,让我们看一下示例(Python-3.5 中)的字节码,看看它的实际效果:

>>> def bar(data0):foo(**data0, b=4)
... 
>>> 
>>> dis.dis(bar)
  1           0 LOAD_GLOBAL              0 (foo)
              3 LOAD_FAST                0 (data0)
              6 LOAD_CONST               1 ('b')
              9 LOAD_CONST               2 (4)
             12 BUILD_MAP                1
             15 BUILD_MAP_UNPACK_WITH_CALL   258
             18 CALL_FUNCTION_KW         0 (0 positional, 0 keyword pair)
             21 POP_TOP
             22 LOAD_CONST               0 (None)
             25 RETURN_VALUE
>>> 

正如你所看到的,在偏移量 15 处我们有BUILD_MAP_UNPACK_WITH_CALL负责解包的字节码。

现在它返回 0 作为结果会发生什么key论证__getitem__ method?

每当解释器在解包过程中遇到异常时,在本例中是一个KeyError,它会停止继续推入/弹出流程,而不是返回变量的实际值,而是返回堆栈效应,这就是为什么键一开始为 0,并且如果每次获得递增结果时不处理异常(由于堆栈大小)。

现在,如果您在 Python-3.6 中执行相同的反汇编,您将得到以下结果:

>>> dis.dis(bar)
  1           0 LOAD_GLOBAL              0 (foo)
              2 BUILD_TUPLE              0
              4 LOAD_FAST                0 (data0)
              6 LOAD_CONST               1 ('b')
              8 LOAD_CONST               2 (4)
             10 BUILD_MAP                1
             12 BUILD_MAP_UNPACK_WITH_CALL     2
             14 CALL_FUNCTION_EX         1
             16 POP_TOP
             18 LOAD_CONST               0 (None)
             20 RETURN_VALUE

在创建局部变量之前(LOAD_FAST) 之后LOAD_GLOBAL有一个BUILD_TUPLE https://docs.python.org/3/library/dis.html#opcode-BUILD_TUPLE它负责创建一个元组并消耗堆栈中的计数项。

BUILD_TUPLE(计数)

创建一个消耗堆栈中 count 个项目的元组,并将 >结果元组推送到堆栈上。

这就是,IMO,为什么你没有得到关键错误,而是得到TypeError。因为在创建参数元组的过程中,它遇到了重复的名称,因此正确地返回TypeError.

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

使用 __getitem__ 就地自定义对象解压不同行为 python 3.5 与 python 3.6 的相关文章

  • 如何从 python 获取 BQL (bLOOMBERG) 查询

    我在 Excel 中使用 BQL 有以下查询 BQL MEMBERS INEMCBI LX Equity type holdings 名称 列 2 行 223 这显示了特定共同基金的证券表 像这样 在此输入图像描述 https i stac
  • 替换字符串列表中的 \x00 的最佳方法?

    我有一个来自已解析 PE 文件的值列表 其中包括 x00每个部分末尾的空字节 我希望能够删除 x00字符串中的字节而不删除所有字节 x 文件中的 s 我试过做 replace and re sub 但并没有取得太大成功 使用Python 2
  • 使用 Django 的 post_save() 信号

    我有两张桌子 class Advertisement models Model created at models DateTimeField auto now add True author email models EmailField
  • 在 Python 中使用 sec 函数的反函数

    我正在创建一个程序 用于计算从一定高度范围和设定初始速度发射射弹的最佳角度 在我需要使用的最终方程中 存在一个反 sec 函数 它导致了一些麻烦 我已经导入了数学并尝试使用 asec 无论如何 但是数学似乎无法计算反秒函数 我也明白 sec
  • Python:当前目录是否自动包含在路径中?

    Python 3 4 通过阅读其他一些 SO 问题 似乎如果moduleName py文件位于当前目录之外 如果要导入它 必须将其添加到路径中sys path insert 0 path to application app folder
  • python ttk treeview:如何选择并设置焦点在一行上?

    我有一个 ttk Treeview 小部件 其中包含一些数据行 如何设置焦点并选择 突出显示 指定项目 tree focus set 什么也没做 tree selection set 0 抱怨 尽管小部件明显填充了超过零个项目 但未找到项目
  • 如何使用 openpyxl 对工作簿中的 Excel 工作表/选项卡进行排序

    我需要按字母数字对工作簿中的选项卡 工作表进行排序 我在用openpyxl https openpyxl readthedocs io en default 操作工作表 您可以尝试排序workbook sheets list workboo
  • 使用 genfromtxt 导入 numpy 中缺失值的 csv 数据

    我有一个 csv 文件 看起来像这样 实际文件有更多的列和行 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 假设文件的名称是info csv如果我尝试使用导入它 data numpy genfromtxt i
  • Python 中的这种赋值方式叫什么? a = b = 真

    我知道关于元组拆包 http docs python org tutorial datastructures html tuples and sequences但是当一行中有多个等号时 这个赋值被称为什么 阿拉a b True 它总是让我有
  • Python While 循环,and (&) 运算符不起作用

    我正在努力寻找最大公因数 我写了一个糟糕的 运算密集型 算法 它将较低的值减一 使用 检查它是否均匀地划分了分子和分母 如果是 则退出程序 但是 我的 while 循环没有使用 and 运算符 因此一旦分子可整除 它就会停止 即使它不是正确
  • Python unicode 字符代码?

    有没有办法将 Unicode 字符 插入 Python 3 中的字符串 例如 gt gt gt import unicode gt gt gt string This is a full block s unicode charcode U
  • 负整数的Python表示

    gt gt gt x 4 gt gt gt print b format x x 4 100 gt gt gt mask 0xFFFFFFFF gt gt gt print b format x mask x mask 4294967292
  • 如何逐像素绘制正方形(Python,PIL)

    在空白画布上 我想使用 Pillow 逐像素绘制一个正方形 我尝试使用 img putpixel 30 60 155 155 55 绘制一个像素 但它没有执行任何操作 from PIL import Image def newImg img
  • FastText - 由于 C++ 扩展未能分配内存,无法加载 model.bin

    我正在尝试使用 FastText Python APIhttps pypi python org pypi fasttext https pypi python org pypi fasttext虽然 据我所知 此 API 无法加载较新的
  • 在 pip.conf 中指定多个可信主机

    这是我尝试在我的中设置的 etc pip conf global trusted host pypi org files pythonhosted org 但是 它无法正常工作 参考 https pip pypa io en stable
  • 在 Tkinter 中使用锚点

    我正在尝试对自动点唱机进行编程 但是我还处于早期阶段 并且在使用时遇到了问题anchor 这是我的代码 from tkinter import from tkinter import messagebox as box def main m
  • 在谷歌C​​olab中使用cv2.imshow()

    我正在尝试通过输入视频来对视频进行对象检测 cap cv2 VideoCapture video3 mp4 在处理部分之后 我想使用实时对象检测来显示视频 while True ret image np cap read Expand di
  • 使用 lambda 函数更改属性值

    我可以使用 lambda 函数循环遍历类对象列表并更改属性值 对于所有对象或满足特定条件的对象 吗 class Student object def init self name age self name name self age ag
  • 将 Scikit-Learn OneHotEncoder 与 Pandas DataFrame 结合使用

    我正在尝试使用 Scikit Learn 的 OneHotEncoder 将 Pandas DataFrame 中包含字符串的列替换为 one hot 编码的等效项 我的下面的代码不起作用 from sklearn preprocessin
  • 从时间序列生成日期特征

    我有一个数据框 其中包含如下列 Date temp data holiday day 01 01 2000 10000 0 1 02 01 2000 0 1 2 03 01 2000 2000 0 3 30 01 2000 200 0 30

随机推荐

  • 如何将 4 维输入输入 LSTM?

    我有一个这种形状的序列输入 6000 64 100 50 The 6000只是样本序列的数量 每个序列是64长度 我计划使用 Keras 将这个输入放入 LSTM 中 我这样设置我的输入 input Input shape 64 100 5
  • OS X 中的窗口移动和调整大小 API

    我试图在 OS X 上找到记录的 或者未记录的 如果这是我唯一的选择 API 以从窗口服务器查询窗口列表 然后使窗口移动和调整大小 有人能指出我正确的方向吗 我想我会从 Win32 下的 FindWindowEx 和 MoveWindow
  • 使用 django-haystack 计算模板中的搜索对象总数

    我使用 django haystack 和 xapian 作为后端搜索引擎 我在用FacetedSearchView and FacetedSearchForm用于对搜索进行分面 我已经通过了searchqueryset to the Fa
  • iPhone 在应用程序启动时出现黑屏

    每当我的应用程序启动时 我都会遇到黑屏 没有错误消息 并且我已在 plist 文件中设置了主 nib 文件 这是我的一些代码 AppDelegate h import
  • 使用 Databricks 将 Google Api 的结果写入数据湖

    我正在通过 Databricks 上的 Python SDK 从 Google 管理报告用户使用情况 Api 获取用户使用情况数据 数据大小约为每天 100 000 条记录 我通过批处理处理了一晚上 API 返回的最大页面大小为 1000
  • 查询统计 MySQL 中表的数量

    我正在增加我拥有的表的数量 有时我很好奇只是想进行快速的命令行查询来计算数据库中的表的数量 那可能吗 如果是这样 查询是什么 SELECT COUNT FROM information schema tables WHERE table s
  • oracle中“tab”表和all_tables的区别

    using 返回哪些表 在 oracle 中 select from tab and select from all tables 我想知道两者之间的区别 tab is an ancient永远不应该使用的数据字典表 它的存在只是为了为几十
  • 如何在 JavaScript 中用 替换 %2C?

    q car category Car 20Audio 2CAccessories brand 我从之前提出的问题中借用了这个函数 function insertParam key value key escape key value esc
  • 不使用 NamespacePrefixMapper 定义 Spring JAXB 命名空间

    随着理解的进展进行大量编辑 是否可以让 Spring Jaxb2Marshaller 使用一组自定义的命名空间前缀 或者至少尊重架构文件 注释中给出的前缀 而不必使用 NamespacePrefixMapper 的扩展 这个想法是让一个类与
  • 单击事件作为 Vue.js 中的 props

    我用 Vue js 创建了一个动态覆盖组件来处理关闭事件 当我们在远离预期对象的屏幕上单击时 该对象会关闭我的问题 这里单击事件不起作用 这是我的代码
  • Datadog 事件触发器不返回任何数据而不是 0

    我创建了一个事件监视器 例如 events sources rds event source db instance by dbinstanceidentifier rollup count last 1d gt 1 但当没有任何事件时它返
  • 如何为 OkHttp3 实现自定义 DNS

    我想创建一个自定义DNS https square github io okhttp 4 x okhttp okhttp3 dns 将 CloudFlare 1 1 1 1 和 1 0 0 1 用于我的所有 RetroFit 连接 这应该取
  • 图像膨胀和腐蚀的实现

    我正在尝试找出一种有效的方法来实现二值图像的图像膨胀和腐蚀 据我了解 天真的方法是 循环遍历图像 如果像素为 1 根据结构元素循环遍历邻域 高度和宽度 膨胀 用图像中的值替换图像的每个像素 SE对应位置 侵蚀 检查所有邻域是否等于SE 如果
  • 在哪里更改 activemq 中的预取值

    我读过有关的文档prefetch buffer 根据我的理解如果我分配Prefetchvalue 1给消费者A Activemq一次向A推送1条消息 一旦A向activemq发送确认 则只有activemq向A推送另一条消息 我的疑问是 我
  • 从 Powerpoint 连接到 SQL Server

    如何从 Powerpoint 2007 年或 2010 年 连接到 SQL 数据库以生成报告 我看过很多论坛 其中大多数都在谈论使用外部工具 Check http www officekb com Uwe Forum aspx powerp
  • 在 Ruby on Rails 中获取每组前 N 个项目

    我有一个包含 日期 和 频率 字段的模型 频率是整数 我正在尝试获取每个日期的前 5 个频率 本质上我想按日期分组 然后获取每组前 5 名 到目前为止 我只检索组中的前 1 个 Observation channel channelOne
  • 将单元格中的 Excel 公式转换为 Python 脚本中的函数

    我一直在尝试将 Excel 工作簿中的公式转换为 Python 脚本中的等效 Python 函数或语句 在我的工作场所 我们有旧的 Excel 工作簿 用于工程过程中的计算 例如设计混凝土结构 这些计算涉及到很多公式以及公式之间的引用 我想
  • SQL中弱相关表的字段映射

    我正在寻找一个 SQL 查询 它可以将一组单独大小的项目映射到一组单独大小的存储桶 我想满足以下条件 桶的大小必须大于或等于项目的大小 每个桶只能包含一件物品 或者留空 每件物品只能放入一个桶中 任何项目都不能拆分到多个存储桶中 我想以某种
  • 即使我正在顺序处理,我也应该阻止吗

    我有一个 Windows 服务 需要定期执行一些工作 所以我设置了一个 System Timers Timer 来执行此操作 我们假设处理时间可能大于计时器间隔 我们还假设如果发生这种情况 那将是一件非常糟糕的事情 为了避免这种情况 我将计
  • 使用 __getitem__ 就地自定义对象解压不同行为 python 3.5 与 python 3.6

    后续问题这个问题 https stackoverflow com questions 50375793 elegant way to have an almost copy constructor that allows to update