pycharm 如何在Python中创建两个具有不同身份但值相同的对象?[副本]

gab6jxml  于 2023-06-23  发布在  PyCharm
关注(0)|答案(3)|浏览(120)

此问题已在此处有答案

Why do different strings have the same ID in Python? [duplicate](1个答案)
8天前关闭
我似乎无法创建两个值相同但标识不同的字符串。我使用的是PyCharm 2023.1,我对Python非常陌生,我刚刚了解了==和is运算符之间的区别,我想 * 实际上 * 亲自看看它们的区别,但无论我怎么尝试Python都只是实习我的字符串并返回True!
我应该说,我知道这个特性是为了优化目的而存在的,我不应该依赖它总是使用is而不是==。我真的只想自己看看区别。
下面是我的原始代码:

firststr= 'blah blah blah'
print(id(firststr))

secondstr= 'blah blah blah'
print(id(secondstr))

print(firststr is secondstr)

这是我得到的结果:

2768763221232
2768763221232
True

首先,我在Google上搜索了这个问题,发现了这个:https://www.jetbrains.com/help/pycharm/variables-loading-policy.html我想也许改变变量加载策略会有所帮助。我想也许是因为它设置在异步上,它创建对象一个接一个,它只是给新的对象,与以前创建的对象具有相同的id,并设置为同步,但没有任何变化!
我问了ChatGPT两次,得到了两个不同的答案:

firststr = 'blah blah blah'
print(id(firststr ))

secondstr= str('blah blah blah' + '')
print(id(secondstr))

print(firststr is secondstr)

和/或

firststr = 'blah blah blah'
print(id(firststr))

secondstr = 'blah blah blah'[:]
print(id(secondstr))

print(firststr is secondstr)

两种方法都不管用,我还是得到了同样的结果。
我在Stackoverflow上发现了一篇旧文章,推荐使用Copy()方法:

import copy

firststr = 'blah blah blah'
print(id(firststr ))

secondstr= copy.copy(firststr)
print(id(secondstr))

print(firststr is secondstr)

和/或

import copy

firststr = 'blah blah blah'
print(id(firststr ))

secondstr= copy.deepcopy(firststr)
print(id(secondstr))

print(firststr is secondstr)

但又一次,他们都不起作用,我得到了同样的结果。
有谁知道我应该如何创建两个值相同但标识不同的字符串吗?

l5tcr1uw

l5tcr1uw1#

有谁知道我应该如何创建两个值相同但标识不同的字符串吗?
你不应该这样。Python保留优化它认为“不可变”的内置类型的权利。这种语言并没有给予你任何方法,你应该创建两个具有相同值但不同标识的不可变类型的对象。这种语言假定 * 您永远不会关心这些类型的区别 *。
你可以依靠关于 * 实现细节 * 的知识来避免某些你知道它会被优化的地方-例如,CPython为内置文字进行常量折叠,如果遇到相同的值,它只是重用它已经创建的对象,如果它在同一个代码块中。它甚至优化了只涉及文字的表达式,所以你可能一开始觉得你会很聪明,用连接运算符构造一个新的字符串,但你会看到:

>>> print("foo" + "bar" is "foobar")
<stdin>:1: SyntaxWarning: "is" with a literal. Did you mean "=="?
True

注意,最新版本的Python实际上会打印警告。
这种情况也发生在其他内置不可变类型上,甚至是像元组这样的容器类型(当然,只适用于只包含其他内置不可变类型的元组:

>>> print((("foo",)+("bar",)) is ('foo', 'bar'))
<stdin>:1: SyntaxWarning: "is" with a literal. Did you mean "=="?
True

实际发生的是,Python正在优化字节码中的this,以引用单个对象:

>>> dis.dis('''print((("foo",)+("bar",)) is ('foo', 'bar'))''')
<dis>:1: SyntaxWarning: "is" with a literal. Did you mean "=="?
  1           0 LOAD_NAME                0 (print)
              2 LOAD_CONST               0 (('foo', 'bar'))
              4 LOAD_CONST               0 (('foo', 'bar'))
              6 IS_OP                    0
              8 CALL_FUNCTION            1
             10 RETURN_VALUE

然而,如果你的表达式不像人们所期望的那样只涉及文字,连接会创建一个新的字符串(因为python不会interning每个创建的字符串):

>>> x = "foo"; y = "bar"; print(x+y is "foobar")
<stdin>:1: SyntaxWarning: "is" with a literal. Did you mean "=="?
False

但是语言并不能保证任何事情。您仍然可能遇到 other 实现细节可能使您意外地无法创建具有相同值但不同标识的字符串的情况。例如,Python intern在示例字典中使用的字符串:

>>> class Foo:
...     def __init__(self):
...         self.foo = 0
...         self.bar = 0
...
>>> Foo()
<__main__.Foo object at 0x103207100>
>>> Foo().__dict__
{'foo': 0, 'bar': 0}
>>> next(iter(Foo().__dict__))
'foo'
>>> "foo" is next(iter(Foo().__dict__))
<stdin>:1: SyntaxWarning: "is" with a literal. Did you mean "=="?
True

所以重申一下,Python没有给你任何方法来做这件事。如果你找到了一种方法,它总是一个实现细节,这是自由的变化未经通知。

>>> import sys; print(sys.version)
3.9.13 (main, May 24 2022, 21:28:44)
[Clang 13.0.0 (clang-1300.0.29.30)]
2jcobegt

2jcobegt2#

您可以通过将初始字符串转换为列表来实现这一点:
第一次:

string = 'blah blah blah'
lst = list(string)
print(lst)
print(id(lst))

输出:

['b', 'l', 'a', 'h', ' ', 'b', 'l', 'a', 'h', ' ', 'b', 'l', 'a', 'h']
139621090396352

第二次:

string = 'blah blah blah'
lst = list(string)
print(lst)
print(id(lst))

输出:

['b', 'l', 'a', 'h', ' ', 'b', 'l', 'a', 'h', ' ', 'b', 'l', 'a', 'h']
139621090349184

为什么需要这样做是完全不同的问题,因为它似乎是id()方法的反模式。

0pizxfdo

0pizxfdo3#

我在电话上写这个解决方案,所以我不能检查这个,但你可以尝试这两个解决方案:
第一:

string1 = "blah blah"
string2 = string1[:]

第二:

string1 = "blah blah"
help_list = list(string1)
string2 = ''.join(help_list)

相关问题