当前位置: 首页 > 面试题库 >

有关python中字符串实例唯一性的问题

聂建茗
2023-03-14
问题内容

我试图找出python仅实例化一次的整数(似乎为-6到256),并且在此过程中偶然发现某些字符串行为,我看不到模式。有时,以不同方式创建的相等字符串共享相同的字符串id,有时不是。这段代码:

A = "10000"
B = "10000"
C = "100" + "00"
D = "%i"%10000
E = str(10000)
F = str(10000)
G = str(100) + "00"
H = "0".join(("10","00"))

for obj in (A,B,C,D,E,F,G,H):
    print obj, id(obj), obj is A

印刷品:

10000 4959776是
10000 4959776是
10000 4959776是
10000 4959776是
10000 4959456错误
10000 4959488错误
10000 4959520错误
10000 4959680错误

我什至没有看到这种模式-除了前四个没有显式的函数调用的事实之外-但肯定不能这样,因为+例如C语言中的“ ”表示对 add
的函数调用。我特别不明白为什么C和G不同,因为这意味着加法的组成部分的ID比结果更重要。

那么,AD受到什么特殊对待,使它们成为同一个实例呢?


问题答案:

在语言规范方面,对于不可变类型的任何实例,完全允许任何兼容的Python编译器和运行时创建新实例,或查找等于所需值的相同类型的现有实例,并使用新引用来同一实例。这意味着is在不可变项之间使用或按ID进行比较总是不正确的,任何次要发行版都可能对此进行调整或更改策略以增强优化。

在实现方面,权衡非常明确:尝试重用现有实例可能意味着花费(也许浪费了)尝试找到这样的实例的时间,但是如果尝试成功,则会节省一些内存(以及分配时间)然后释放用于保存新实例所需的内存位)。

如何解决这些实现方面的折衷方案并不完全清楚-如果您可以找出启发式方法,表明有可能找到合适的现有实例,并且搜索(即使失败)也会很快,那么您可能想要尝试搜索-
-启发式提示时重用,否则跳过。

在您的观察中,您似乎发现了一种特殊的点释放实现,该实现在完全安全,快速且简单的情况下执行了一些窥孔优化,因此A到D的分配都归结为与A完全相同(但E到F不这样做,因为它们涉及命名函数或方法,优化器的作者可能合理地认为,假设语义不是100%安全的-
如果这样做的话,则是低投资回报率的-因此未对窥视孔进行优化)。

因此,A到D重用相同的实例归结为A和B这样做(因为C和D被窥视孔优化为完全相同的构造)。

反过来,这种重用清楚地表明了编译器策略/优化器试探法,即将同一函数的本地名称空间中不变类型的相同文字常量折叠为对函数中一个实例的引用.func_code.co_consts(使用当前CPython的术语表示函数和代码的属性)对象)-合理的策略和试探法,因为在一个函数中重复使用相同的不变常量文字有些频繁,并且价格仅需支付一次(在编译时),而优势却可以多次获得(每次函数运行时,可能在循环内等)。

(碰巧的是,鉴于这些明确的权衡取舍,这些特定的策略和启发式方法已在CPython的所有最新版本中普遍存在,并且我相信IronPython,Jython和PyPy也是如此;-)。

如果您打算为Python本身或类似语言编写编译器,运行时环境,窥孔优化器等,这是一个值得研究的有趣话题。我猜想对内部结构进行深入研究(当然,最好是对许多不同的正确实现进行研究,以免专注于特定的怪癖——Python目前至少拥有4种独立于生产的实现,这是一件好事,更不用说了每个版本都有多个版本!)还可以间接地帮助一个更好的Python程序员-
但是,重点放在语言本身所 保证 的内容上尤其重要,这要比单独的实现中常见的要少一些,因为“正好发生”的部分
__(如果语言规范如此),则在下一个版本或另一个实现的下一个发行版时,您可能会完全改变,并且,如果您的生产代码错误地依赖于此类详细信息,则可能会导致令人讨厌的意外;-)。
另外-几乎不必依赖于这样的可变实现细节而不是依赖于语言规定的行为(除非您要编写诸如优化器,调试器,分析器之类的代码;- )。



 类似资料:
  • 问题内容: 我想将字符添加到字符串中,但要确保最终列表中的所有字母都是 唯一的 。 例如:→ 现在,我当然想到了两种解决方案。一种是使用,它将字符与ASCII码映射。因此,每当我遇到一个字母时,它都会将索引设置为。之后,我将扫描列表并附加所有已设置的列表。时间复杂度为 O(n) 。 另一个解决方案是使用和遵循相同的过程。映射完每个字符后,我将对字典中的每个键进行操作。这也将具有 线性 运行时间。

  • 问题内容: 这个简单的代码仅尝试用冒号替换分号(在i指定的位置)不起作用: 它给出了错误 如何解决此问题,以冒号代替分号?使用replace不起作用,因为该函数不占用索引-可能有一些我不想替换的分号。 例 在字符串中,我可能有许多分号,例如 我知道我想替换哪些(我在字符串中有索引)。使用替换无法正常工作,因为我无法对其使用索引。 问题答案: python中的字符串是不可变的,因此你不能将它们视为列

  • 问题内容: 考虑以下代码: 使用new关键字时,Java会 再次创建吗?这将存储在常规堆还是池中?多少人在将s结尾池? 问题答案: 如果使用关键字,将创建一个新对象。请注意,对象始终在堆上-字符串池不是与堆分开的独立内存区域。 字符串池就像一个缓存。如果你这样做: 那么Java编译器是聪明足以让只有一个对象,并且将两者指的是同一个String对象。如果你这样做: 那么池中将有一个对象,该对象代表文

  • 问题内容: 我正在编写一个程序,该程序将以字符串形式输出唯一字符(通过扫描仪输入)。我创建了一个方法来尝试实现此目的,但我一直在获取不重复的字符,而不是字符串中唯一的一个(或多个)字符。我只想要唯一的字母。 这是我的代码: 这是上面代码的示例输出: 预期的输出将是: 问题答案: 根据所需的输出,当以后重复时,必须替换最初已经添加的字符,因此:

  • 本文向大家介绍Python字符串和字典相关操作的实例详解,包括了Python字符串和字典相关操作的实例详解的使用技巧和注意事项,需要的朋友参考一下 Python字符串和字典相关操作的实例详解 字符串操作: 字符串的 % 格式化操作: 输出结果: 模板字符串: 字符串格式化类型: (1) %字符:标记转换说明符的开始,就是开始替换。 (2) -表示左对齐,+表示在转换值之前加上正负号。0表示转换值位

  • 问题内容: 上下文:我是CS n00b,正在通过“破解编码面试”来完成自己的工作。第一个问题要求“实施一种算法以确定字符串是否具有所有唯一字符”。我的(可能是幼稚的)实现如下: 作者建议以下实现: 是什么使作者的实现比我的更好(FWIW,作者的解决方案是在Java中,我将其转换为Python -我的解决方案是无法在Java中实现的解决方案)吗?或者,更一般而言,解决该问题需要什么?我采用的方法有什