operator模块可以轻松避免不必要的函数和lambda 在这种情况下:
import operator
def mytest(op, list1, list2):
ok = [op(i1, i2) for i1, i2 in zip(list1, list2)]
return all(ok)
mytest(operator.eq, [1, 2, 3], [1, 2, 3]) # True
mytest(operator.add, [-1, 2, -3], [1, -2, 33]) # False
好吧,现在我需要做i1 and i2
,但令我惊讶的是,我在操作员模块中找不到and
!这同样适用于or
!我知道,and
不完全是运算符,它是关键字,但是not
,还有is
甚至{{1所有关键字都包括在内。
那故事是什么?他们为什么失踪?
答案 0 :(得分:9)
因为您无法将布尔运算符转换为python函数。函数总是评估它们的参数,而布尔运算符则不会。将and
和or
添加到运算符模块还需要添加一种特殊类型的函数(如lisp“宏”),以按需评估其参数。显然,这不是python设计师想要的东西。考虑:
if obj is not None and obj.is_valid():
....
你不能以功能形式写这个。尝试
if operator.xyz(obj is not None, obj.is_valid())
如果obj
实际为None
,则将失败。
答案 1 :(得分:3)
你可以自己编写这些,但你需要为第二个参数传递一个函数(例如lambda),以防止它在调用时被评估,假设通常的短路行为对你很重要。 / p>
def func_or(val1, fval2):
return val1 or fval2()
def func_and(val1, fval2):
return val1 and fval2()
用法:
func_or(False, lambda: True)
func_and(True, lambda: False)
答案 2 :(得分:1)
没有operator.and
的原因是and
是关键字,因此它是SyntaxError
。
正如tgh435所解释的那样,and
中没有重命名operator
函数的原因是它会产生误导:函数调用总是评估其操作数,但and
运算符不会。 (对于其他一致且简单的规则,这也是一个例外。)
在您的情况下,看起来您根本不关心短路,因此可以轻松构建您自己的版本:
def and_(a, b):
return a and b
或者,如果您只使用一次,甚至内联:
mytest(lambda a, b: a and b, [-1, 2, -3], [1, -2, 33])
在某些情况下,值得查看all
(以及or
,any
)。它实际上被短路and
扩展到任意操作数。当然,它具有与operator
函数不同的API,采用单个可迭代的操作数而不是两个单独的操作数。它的短路方式也不同;它只是停止迭代迭代,这只有在你设置的时候才有用,所以iterable只是根据需要进行评估。因此,它通常不能作为替代品使用 - 但如果您稍微重构代码,它有时是可用的。
答案 3 :(得分:0)
Python的WKWebView
和class YouTubeVideoPlayerVC: UIViewController {
@IBOutlet weak var videoPlayerView: WKWebView!
var videoURL:URL! // has the form "https://www.youtube.com/embed/videoID"
var didLoadVideo = false
override func viewDidLoad() {
super.viewDidLoad()
videoPlayerView.configuration.mediaTypesRequiringUserActionForPlayback = []
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
// Size of the webView is used to size the YT player frame in the JS code
// and the size of the webView is only known in `viewDidLayoutSubviews`,
// however, this function is called again once the HTML is loaded, so need
// to store a bool indicating whether the HTML has already been loaded once
if !didLoadVideo {
videoPlayerView.loadHTMLString(embedVideoHtml, baseURL: nil)
didLoadVideo = true
}
}
var embedVideoHtml:String {
return """
<!DOCTYPE html>
<html>
<body>
<!-- 1. The <iframe> (and video player) will replace this <div> tag. -->
<div id="player"></div>
<script>
var tag = document.createElement('script');
tag.src = "https://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
var player;
function onYouTubeIframeAPIReady() {
player = new YT.Player('player', {
height: '\(videoPlayerView.frame.height)',
width: '\(videoPlayerView.frame.width)',
videoId: '\(videoURL.lastPathComponent)',
events: {
'onReady': onPlayerReady
}
});
}
function onPlayerReady(event) {
event.target.playVideo();
}
</script>
</body>
</html>
"""
}
}
语法无法直接映射到函数。这些语法是惰性求值的:如果表达式左侧部分的结果允许知道整个表达式的值,则跳过右侧部分。由于它们引入了流量控制,因此无法使用操作员再现它们的行为。
为了减少混淆,python选择不提供这些方法。
georg给出了and
懒惰很重要的一个很好的例子:
or
现在,如果您不需要延迟评估,可以使用abarnert的答案实现:
and
用法:
if obj is not None and obj.is_valid():
...
如果您需要延迟评估,可以使用kindall的答案实施:
def and_(a, b):
return a and b
def or_(a, b):
return a or b
用法:
>>> or_(False, True)
>>> and_(True, False)
注意:
如评论中所述,函数def func_or(val1, fval2):
return val1 or fval2()
def func_and(val1, fval2):
return val1 and fval2()
和>>> func_or(False, lambda: True)
>>> func_and(True, lambda: False)
对应于按位运算符operator.and_
和operator.or_
。请参阅:https://docs.python.org/3/library/operator.html#mapping-operators-to-functions
请注意,未使用名称&
和|
:operators.and
和operators.or
是Python关键字,因此会出现语法错误。