x 或 y:可接受的习语,还是混淆?
我必须从可能为 None 的变量中提取值,并考虑一些默认值。我首先写了这段代码:
if self.maxTiles is None:
maxX, maxY = 2, 2
else:
maxX, maxY = self.maxTiles
然后我意识到我可以将其缩短为:
maxX, maxY = self.maxTiles if self.maxTiles is not None else (2, 2)
但后来我意识到这可能是最简洁且易于阅读的:
maxX, maxY = self.maxTiles or (2, 2)
后者是可以接受的,还是太黑客化了?
I have to extract values from a variable that may be None, with some defaults in mind. I first wrote this code:
if self.maxTiles is None:
maxX, maxY = 2, 2
else:
maxX, maxY = self.maxTiles
Then I realized I could shorten it to:
maxX, maxY = self.maxTiles if self.maxTiles is not None else (2, 2)
But then I realized this might be the most succinct and easily readable:
maxX, maxY = self.maxTiles or (2, 2)
Is the latter acceptable, or too hackish?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
具体来说,
我发现一般形式
if not A: B else: C
的“双重否定”(无论是作为语句还是表达式)可能会非常令人困惑/误导;这实际上并不是一个if not .. else
,但是移动not
并不会让“双重否定”消失。因此,一般来说,我只是将此类构造重写为
if A: C else: B
。在这种特殊情况下,如果我确实选择了三元运算符形式,我会将其编码为On 来解决更一般的问题:
a = b or c
很好当且仅当< /em> 你确实想使用c
来表示b
的任何假值——这是不好处理的特别是b
为None
。 IOW,b 或 c
是一种更好的表达方式,但它不是一种表达核心测试的类似表达式的方式,相反,
b is None< /代码>。理论上,如果您“知道”
b
唯一可能的假值是None
,那么它们在语义上是等效的,但是强“唯一可能的假值”约束将对于代码的读者/维护者来说并不明显 - 如果您必须添加注释来解释这一点,则或
可能声称的任何简洁性优势都将无效......在可行的情况下,更好的是“用代码说出来”,而不是让代码晦涩难懂,需要注释来明确它在做什么和何时(真正有用的注释是那些解释的注释,而不是解释什么和何时[[代码本身应该表明!-)]],而是为什么,当它不明显时——这个特定的代码功能的应用程序目的是什么)。About, specifically,
I've found that "double negatives" of the general form
if not A: B else: C
(whether as statements or expressions) can be quite confusing / misleading; this isn't literally anif not .. else
, but moving thenot
doesn't make the "double negative" go away.So, in general, I just rewrite such constructs to
if A: C else: B
. In this particular case, if I did choose the ternary-operator form, I'd code it asOn to the more general question:
a = b or c
is fine if and only if you really want to usec
for any false value ofb
-- it's not fine to deal specifically withb
beingNone
. IOW,b or c
is a better way to expressbut it's not a way to express a similar expression where the core test is, instead,
b is None
. In theory, if you "know" that the only possible false value forb
isNone
, they're semantically equivalent, but that strong "only possible false value" constraint will not be apparent to readers / maintainers of your code -- and if you have to add a comment to explain that, any conciseness advantages thator
might claim are nullified... better, when feasible, to "say it in code", rather than have the code be obscure and need comments to clarify exactly what it's doing and when (comments that are really useful are rather those which explain, not the what and the when [[the code itself should show that!-)]], but rather the why when it's not obvious -- what's the application purpose being served by this specific tidbit of code functionality).连同 gddc 的答案(假设 maxTiles 是一个元组的问题),我可能会选择第二个选项,但为了清楚起见添加括号:
Along with the answer of gddc ( of the problems of assuming maxTiles is a tuple), I would probably do the second option, but add parenthesis for clarity:
如果您在 函数的开头,我会使用较长的形式,因为它更惯用且易于识别。是的,行数更多,但几乎没有保存任何字符,而且适合 79 个字符行的短行=很好。
另外,如果您必须调整逻辑或添加更多步骤,无论如何您都可能会恢复为长形式。
If you're doing this at the beginning of a function, I'd use the longer form as it's more idiomatic and instantly recognizable. Yeah, it's more lines, but you barely save any characters, and short lines that fit into 79 character lines = good.
Plus if you ever have to adjust the logic or add more steps you'd likely revert to the long form anyways.
我尽可能避免使用
y if x else z
语法。它本质上是一种丑陋、不直观的语法,也是 Python 设计中最大的错误之一。这是一个无序表达式:x 在 y 之前计算。这很不直观;它自然地读作“如果x则y,否则z”。 C 的语法为我们提供了几十年来建立的、普遍理解的顺序:x? y:z
。 Python 在这一点上犯了很大的错误。也就是说,三元语法无论如何都是提供默认值的错误机制。在 self.maxTiles 中,如果 self.maxTiles 不是 None else (2, 2),请注意冗余:您必须指定 self.maxTiles 两次。这是重复的,因此需要更多的工作来阅读代码。我必须读两遍以确保它没有说,例如,
self.minTiles if self.maxTiles is not None else (2, 2)
。self.maxTiles or (0,2)
避免了这些问题;一目了然。需要注意的是:如果 self.maxTiles 是
()
或0
或其他一些错误值,则结果会有所不同。根据您似乎正在做的事情,这可能是可以接受的,但请记住这一点。当为布尔值或整数提供默认值时,这是一个问题,并且您确实需要is None
测试。对于那些我更喜欢简单的条件,但有时会求助于三元表达式。编辑;编写条件版本的更清晰的方法是:
I avoid the
y if x else z
syntax when I can. It's inherently an ugly, unintuitive syntax, and one of the bigger mistakes in Python's design. It's an out-of-order expression: x is evaluated before y. It's unintuitive; it's naturally read as "if x then y, else z". C's syntax gives us a decades-established, universally-understood order for this:x? y:z
. Python got this one very wrong.That said, ternary syntax is the wrong mechanism for supplying a default anyway. In
self.maxTiles if self.maxTiles is not None else (2, 2)
, note the redundancy: you have to specifyself.maxTiles
twice. That's repetitive, so it takes more work to read the code. I have to read it twice to be sure it doesn't say, for example,self.minTiles if self.maxTiles is not None else (2, 2)
.self.maxTiles or (0,2)
avoids these problems; it's perfectly clear at a glance.One caveat: if self.maxTiles is
()
or0
or some other false value, the result is different. This is probably acceptable based on what you seem to be doing, but keep this in mind. It's an issue when providing a default for a boolean or an integer, and you really do need theis None
test. For those I prefer a simple conditional, but will sometimes fall back on a ternary expression.Edit; a clearer way of writing the conditional version is:
你的代码是完全可以接受的习惯用法。事实上,我发现它比前两个更具可读性。
我唯一的考虑是你在一行中做两件事,提供默认值并将它们解压到 x,y 中。如果把它们分成两部分可能会更清楚。
这也转移了gddc的批评,尽管这并不是很严重的批评。
You code is perfectly acceptable idiom. In fact I find it more readable than the first two.
My only consideration is you are doing two things in one line, to supply a default and to unpack them into x,y. It maybe more clear if you separate them into two.
This also deflect the criticism of g.d.d.c, although it is not really a serious one.
我不喜欢使用
or
和and
作为 Python 中三元运算符的替代品。当我只想检查None
时,我多次遇到过诸如0
值被视为“false”的问题。我认为最好是明确的,即使它更冗长,所以你的第二个例子是最好的:I don't like using
or
andand
as replacements for a ternary operator in Python. I've run into problems like a0
value being treated as "false" too many times, when I only intended to check forNone
. I consider it much better to be explicit, even if its more verbose, so your second example is best: