关于list
首先是非常重要的一点,我希望从这一点开始一切都会发生。
在普通的Python中,list在任何方面都不是特别的(除了具有用于构造的可爱语法之外,这主要是一个历史性的意外)。一旦创建了列表[3,2,6],它就只是一个普通的Python对象,比如数字3、集合{3,7},或者函数lambda x: x+5。
(是的,它支持更改元素,支持迭代和许多其他事情,但这正是类型的含义:它支持一些操作,而不支持其他操作。int支持提升到一个幂,但这并不意味着它很特别——它只是一个int。lambda支持调用,但这并不意味着它非常特殊——毕竟,这就是lambda的用途:)。
关于and
and不是运算符(您可以称之为“operator”,但也可以称之为“for”运算符:)。Python中的运算符是(通过)对某种类型的对象调用的方法,通常作为该类型的一部分编写。方法无法对其某些操作数进行求值,但and可以(而且必须)这样做。
其结果是and不能重载,就像for不能重载一样。它是完全通用的,通过指定的协议进行通信。您可以做的是自定义协议的部分,但这并不意味着您可以完全改变and的行为。协议是:
想象一下Python对“a和b”的解释(这不是按字面意思发生的,但它有助于理解)。当谈到“and”时,它会看着它刚刚评估过的对象(a),问它:你是真的吗?(不是:你是不是True?)如果您是a的类的作者,则可以自定义此答案。如果a回答“否”,则and(完全跳过b,它根本不计算,并且)说:a是我的结果(不是:False是我的结果)。
如果a不回答,那么and会问:你的长度是多少?(同样,您可以将其自定义为a类的作者)。如果a回答0,则and执行与上面相同的操作-认为它为false(不是false),跳过b,并给出a结果。
如果a对第二个问题(“你的长度是多少”)回答的不是0,或者根本没有回答,或者对第一个问题(“你是真的”)回答的是“是”,那么and对b求值,并说:b是我的结果。注意,它不会问任何问题。
另一种说法是,a and b与b if a else a几乎相同,只是a只计算一次。
现在,拿着纸和笔坐几分钟,让自己相信当{a,b}是{True,False}的子集时,它的工作方式与您对布尔运算符的预期完全一样。但我希望我已经说服你,它是更普遍的,正如你将看到的,更有用的方式。
把这两个放在一起
现在我希望你理解你的例子1。and不关心mylist1是数字、列表、lambda还是类Argmhbl的对象。它只关心mylist1对协议问题的回答。当然,mylist1回答了关于长度的问题5,所以返回mylist2。就这样。它与mylist1和mylist2的元素无关-它们在任何地方都不会进入图片。
第二个例子:&在list上
另一方面,&是一个类似于其他任何运算符的运算符,例如+。可以通过在某个类上定义特殊方法来为该类型定义它。int将其定义为按位“and”,bool将其定义为逻辑“and”,但这只是一个选项:例如,集合和其他一些对象(如dict keys视图)将其定义为集合交集。list只是没有定义它,可能是因为Guido没有想到任何明显的de方法完成它。
纽比
另一方面,-D,numpy数组是特殊的,或者至少他们正在尝试这样做。当然,numpy.array只是一个类,它不能以任何方式重写and,所以它做了下一件最好的事情:当被问到“你是真的”时,numpy.array会抛出一个ValueError,实际上是在说“请重新表述问题,我的真理观不适合你的模型”。(请注意,ValueError消息没有提到and,因为numpy.array不知道是谁在问这个问题;它只谈到了真相。)
对于&,这是完全不同的故事。array可以随心所欲地定义它,并且它与其他操作符一致地定义&:pointwise。所以你终于得到了你想要的。
HTH公司