非常简单的问题,但对我来说是一个好奇心......
假设我们有一个字符串项目列表。如果我们对列表中的每个元素调用内置函数str
,这似乎是多余的,因为这些项目已经是字符串。引擎盖下会发生什么,特别是对于 Python,但也对其他语言感兴趣。解释器是否已经看到该项目是一个字符串而不调用该str
函数?或者它无论如何都会这样做并返回一个字符串,一个字符串的字符串是什么意思?
非常简单的问题,但对我来说是一个好奇心......
假设我们有一个字符串项目列表。如果我们对列表中的每个元素调用内置函数str
,这似乎是多余的,因为这些项目已经是字符串。引擎盖下会发生什么,特别是对于 Python,但也对其他语言感兴趣。解释器是否已经看到该项目是一个字符串而不调用该str
函数?或者它无论如何都会这样做并返回一个字符串,一个字符串的字符串是什么意思?
测试很简单:
>>> a = 'a'
>>> id(a)
4298835424
>>> id(str(a))
4298835424
>>> a is str(a)
True
它是相同的对象。
经过测试并与 CPython 2.7.、3.3.、PyP 1.9.、IronPython 2.0 一起使用
不适用于Jython 2.5:
Jython 2.5.2 (Release_2_5_2:7206, Mar 2 2011, 23:12:06)
[Java HotSpot(TM) 64-Bit Server VM (Apple Inc.)] on java1.6.0_45
Type "help", "copyright", "credits" or "license" for more information.
>>> a = 'a'
>>> id(a)
2
>>> id(str(a))
3
>>> id(str(a))
4
>>> a is str(a)
False
调用字符串对象时,将执行str
底层函数。__str__(self)
返回原始对象(python字符串大小写)还是副本取决于函数的实现。
一般来说,我认为该语言不会或很少处理冗余调用。程序本身将决定行为。(即是否在对象上定义了命名函数,如果没有将发出错误。)
让我们换一种方式思考。如果您对 C++ 有所了解,那么在 C++ 中有一种复制构造函数。它同样面临依赖于您的实现的深层复制和卷影复制问题。
Python 调用str
:
dis.dis(compile("str('a')", '<none>', 'eval'))
1 0 LOAD_NAME 0 (str)
3 LOAD_CONST 0 ('a')
6 CALL_FUNCTION 1
9 RETURN_VALUE
但这只是返回相同的字符串:
In [11]: str('a') is 'a'
Out[11]: True
通常首先要检查类__init__
是它是否已经是该类的一个实例(如果是,则按原样返回)......
如果数据类型是不可变的并且已经是相同的类型,那么 Python 只需返回原始数据类型,例如与元组相同。
>>> help(str)
Help on class str in module __builtin__:
class str(basestring)
| str(object='') -> string
|
| Return a nice string representation of the object.
| If the argument is a string, the return value is the same object.