在下面的视频中,作者给一个QBarSet分配了多个值我不太明白“<<" . In python, this is a left shift operator. In c++ example (see the link), it was just like what is seen in the python code. Can anyone please explain what is multiple "<<" doing in this python code? Can python directly translate c++ code here?
”做了什么@29:32
在 Python 中,与 C++ 和许多其他语言一样,运算符可以并且经常被重写,以便从通常不支持它们的类中获得特殊行为。
PyQt(如 PySide)只是重写了 C++ API 中也被重写的运算符,以提供一致的语法。
当您使用
set0 << 1
时,您实际上并不是进行位移位,而是使用与 C++ 中重写运算符中发生的操作相同的操作,即将值附加到条形集合中。
Python 并不“直接翻译 C++ 代码”。 Qt 绑定只是为了使其语法与官方 C++ API 一致而实现的。
具体来说,
<<
对应于__lshift__
方法,这意味着如果您创建一个子类并重写该方法,结果是每当该类的实例后面跟着<<
时,就会调用该重写使用以下对象,而不是使用默认的数字行为。
例如:
class Test(object):
def __init__(self, value):
self.value = value
def __lshift__(self, other):
# "other" is the object on the right hand of the operator
return self.value * other.value
>>> a = 2
>>> b = 3
>>> print(a << b) # same as 2 << 3
16
>>> a = Test(2)
>>> b = Test(3)
>>> print(a << b)
6
上面的例子显然没有多大意义,但重写运算符是很常见的,以便提供语法糖,可以使语法更简洁,同时保持足够清晰。
最简单的例子是用于连接文本的
+
运算符:字符串显然不支持数学加法,但是 'a' + 'b'
可以工作,因为在内部,__add__
被重写以返回两个字符串的连接。
Python 实现中也存在类似情况,也涉及按位运算符,例如从 3.9 开始为
|
引入的 |=
和 dict
:
dict_a |= dict_b
(几乎)相当于:
dict_a.update(dict_b)
通常,特定运算符的使用遵循其实现背后的逻辑,就像上面的 dict 情况一样,或用于
set()
的类似运算符:为集合中的项目维护按位运算 |
或 &
的逻辑.
但有时,用法更“图形化”,就像手头的例子一样。例如,某些模块重写
>>
(__rshift__
) 和其他运算符来创建“对象链”,这些对象比使用更详细的语法更容易编写和读取,例如创建一个以各种方式处理信号的过滤器链。返回结果之前的方法。
&QBarSet::operator<<(const qreal &value)
将右手写的值附加到条形集合中(相当于append()
:<<
的含义主要是说“将一个值放入该对象”) ”.__lshift__
并获得相同的行为来遵循相同的概念。
考虑完整语法之间的差异:
set0.append(1)
set0.append(2)
set0.append(3)
set0.append(4)
set0.append(5)
set0.append(6)
甚至更“优雅”的比如:
values = 1, 2, 3, 4, 5, 6
for v in values:
set0.append(v)
以及以下语法,使用方便的运算符覆盖:
set0 << 1 << 2 << 3 << 4 << 5 << 6
即使不知道类和运算符的底层行为,语法仍然足够清晰。
QRect::operator|=(QRect)
相当于united()
,它返回包含两个矩形的边界矩形:
full = QRect()
for other in listOfRectangles:
full = full.united(other)
# or
full |= other
PyQt 还自己实现了一些运算符(其中许多在 PySide 中未使用)。例如,它
QRect.contains()
使用 __contains__
覆盖,这是有道理的,因为它是在使用语法 x in y
: 时调用的
p = QPoint(2, 5)
r = QRect(0, 0, 10, 10)
print(r.contains(p))
# equivalent to
print(p in r)
阅读有关 Python 数据模型和所有“神奇方法”(也称为 dunder 方法,如双下划线)的更多信息,并考虑并非所有 Qt 运算符在 Python 中始终可用,反之亦然(检查官方 Qt C++ API、PyQt/PySide 文档 和 交互式 Python shell 中的
help()
)。