为什么+(plus)可以连接Python中的两个字符串?
Why does + (plus) can concatenate two strings in Python?
我正在学习 Python 困难的学习方式。
w = "This is the left side of..."
e = "a string with a right side."
print w + e
解释为什么用 + 添加两个字符串 w
和 e
会得到更长的字符串。
即使我知道它可以工作,但我不明白为什么以及如何?请帮助我。
+
、-
、*
和其他运算符将处理任何实现正确方法的操作。由于字符串实现了 __add__(self, other)
方法,您可以使用 +
.
添加两个字符串
试试这个:定义您自己的字符串子类并覆盖它的 __add__
方法:
class BadString(str):
def __add__(self, other):
# Ignore both input strings and just return this:
return "Nothing Useful"
s = BadString("hello")
print("hello" + " world") # "hello world"
print(s + "world") # "Nothing Useful"
相同的技术,运算符重载,让您创建 类 可以使用 built-in 运算符,如 +
或 *
有用,就像可以添加的向量在一起。
当您以这种方式添加(连接)两个字符串时,将调用 class str
的 __add__
方法。 __add__
方法是这样工作的,但以下内容并非源代码中的逐字记录:
def __add__(self, str1, str2):
str3 = [str1] #Convert to list
str3.append(str2) #Add the second string to the list
return ''.join(str3) #Return the two joined
示例:
class MyString:
def __init__(self, initstr):
self.string = initstr
def __add__(str1, str2):
str3 = [str1.string] #Convert to list
str3.append(str2.string) #Add the second string to the list
return MyString(''.join(str3)) #Return the two joined
>>> a = MyString("Hello")
>>> b = MyString(" World!")
>>> c = a+b
>>> c.string
'Hello World!'
>>>
Python 使用 +
连接字符串,因为那是 Python 的核心开发人员定义该运算符的方式。
虽然 __add__
special method is normally used to implement the +
operator, +
(BINARY_ADD
bytecode instruction) 确实 不 调用 str.__add__
因为 +
在 Python 2 中特别对待字符串和 Python 3. 如果 +
的两个操作数都是字符串,Python 直接调用字符串连接函数 ,从而无需调用特殊方法。
Python 3 调用 unicode_concatenate
(source code):
TARGET(BINARY_ADD) {
PyObject *right = POP();
PyObject *left = TOP();
PyObject *sum;
if (PyUnicode_CheckExact(left) &&
PyUnicode_CheckExact(right)) {
sum = unicode_concatenate(left, right, f, next_instr);
/* unicode_concatenate consumed the ref to v */
}
else {
sum = PyNumber_Add(left, right);
Py_DECREF(left);
}
...
Python 2 调用 string_concatenate
(source code):
case BINARY_ADD:
w = POP();
v = TOP();
if (PyInt_CheckExact(v) && PyInt_CheckExact(w)) {
/* INLINE: int + int */
register long a, b, i;
a = PyInt_AS_LONG(v);
b = PyInt_AS_LONG(w);
/* cast to avoid undefined behaviour
on overflow */
i = (long)((unsigned long)a + b);
if ((i^a) < 0 && (i^b) < 0)
goto slow_add;
x = PyInt_FromLong(i);
}
else if (PyString_CheckExact(v) &&
PyString_CheckExact(w)) {
x = string_concatenate(v, w, f, next_instr);
/* string_concatenate consumed the ref to v */
goto skip_decref_vx;
}
else {
slow_add:
x = PyNumber_Add(v, w);
...
此优化自 2004 年以来一直在 Python。来自 issue980695:
... in the attached patch ceval.c special-cases addition of two strings (in the same way as it special-cases addition of two integers already)
但请注意,主要目标不仅仅是消除特殊属性查找。
就其价值而言,str.__add__
仍按预期工作:
>>> w.__add__(e)
'This is the left side of...a string with a right side.'
和Python将调用str
的子类的__add__
方法,因为PyUnicode_CheckExact(left) && PyUnicode_CheckExact(right)
(或PyString_CheckExact(v) && PyString_CheckExact(w)
,在Python 2)上面的代码片段将是错误的:
>>> class STR(str):
... def __add__(self, other):
... print('calling __add__')
... return super().__add__(other)
...
>>> STR('abc') + STR('def')
calling __add__
'abcdef'
我正在学习 Python 困难的学习方式。
w = "This is the left side of..."
e = "a string with a right side."
print w + e
解释为什么用 + 添加两个字符串 w
和 e
会得到更长的字符串。
即使我知道它可以工作,但我不明白为什么以及如何?请帮助我。
+
、-
、*
和其他运算符将处理任何实现正确方法的操作。由于字符串实现了 __add__(self, other)
方法,您可以使用 +
.
试试这个:定义您自己的字符串子类并覆盖它的 __add__
方法:
class BadString(str):
def __add__(self, other):
# Ignore both input strings and just return this:
return "Nothing Useful"
s = BadString("hello")
print("hello" + " world") # "hello world"
print(s + "world") # "Nothing Useful"
相同的技术,运算符重载,让您创建 类 可以使用 built-in 运算符,如 +
或 *
有用,就像可以添加的向量在一起。
当您以这种方式添加(连接)两个字符串时,将调用 class str
的 __add__
方法。 __add__
方法是这样工作的,但以下内容并非源代码中的逐字记录:
def __add__(self, str1, str2):
str3 = [str1] #Convert to list
str3.append(str2) #Add the second string to the list
return ''.join(str3) #Return the two joined
示例:
class MyString:
def __init__(self, initstr):
self.string = initstr
def __add__(str1, str2):
str3 = [str1.string] #Convert to list
str3.append(str2.string) #Add the second string to the list
return MyString(''.join(str3)) #Return the two joined
>>> a = MyString("Hello")
>>> b = MyString(" World!")
>>> c = a+b
>>> c.string
'Hello World!'
>>>
Python 使用 +
连接字符串,因为那是 Python 的核心开发人员定义该运算符的方式。
虽然 __add__
special method is normally used to implement the +
operator, +
(BINARY_ADD
bytecode instruction) 确实 不 调用 str.__add__
因为 +
在 Python 2 中特别对待字符串和 Python 3. 如果 +
的两个操作数都是字符串,Python 直接调用字符串连接函数 ,从而无需调用特殊方法。
Python 3 调用 unicode_concatenate
(source code):
TARGET(BINARY_ADD) {
PyObject *right = POP();
PyObject *left = TOP();
PyObject *sum;
if (PyUnicode_CheckExact(left) &&
PyUnicode_CheckExact(right)) {
sum = unicode_concatenate(left, right, f, next_instr);
/* unicode_concatenate consumed the ref to v */
}
else {
sum = PyNumber_Add(left, right);
Py_DECREF(left);
}
...
Python 2 调用 string_concatenate
(source code):
case BINARY_ADD:
w = POP();
v = TOP();
if (PyInt_CheckExact(v) && PyInt_CheckExact(w)) {
/* INLINE: int + int */
register long a, b, i;
a = PyInt_AS_LONG(v);
b = PyInt_AS_LONG(w);
/* cast to avoid undefined behaviour
on overflow */
i = (long)((unsigned long)a + b);
if ((i^a) < 0 && (i^b) < 0)
goto slow_add;
x = PyInt_FromLong(i);
}
else if (PyString_CheckExact(v) &&
PyString_CheckExact(w)) {
x = string_concatenate(v, w, f, next_instr);
/* string_concatenate consumed the ref to v */
goto skip_decref_vx;
}
else {
slow_add:
x = PyNumber_Add(v, w);
...
此优化自 2004 年以来一直在 Python。来自 issue980695:
... in the attached patch ceval.c special-cases addition of two strings (in the same way as it special-cases addition of two integers already)
但请注意,主要目标不仅仅是消除特殊属性查找。
就其价值而言,str.__add__
仍按预期工作:
>>> w.__add__(e)
'This is the left side of...a string with a right side.'
和Python将调用str
的子类的__add__
方法,因为PyUnicode_CheckExact(left) && PyUnicode_CheckExact(right)
(或PyString_CheckExact(v) && PyString_CheckExact(w)
,在Python 2)上面的代码片段将是错误的:
>>> class STR(str):
... def __add__(self, other):
... print('calling __add__')
... return super().__add__(other)
...
>>> STR('abc') + STR('def')
calling __add__
'abcdef'