多个对象从方法返回,但行为不如预期。

huangapple go评论76阅读模式
英文:

Multiple object returns from method not acting as expected

问题

在使用pyautogui时,我决定创建一个方法,根据我的显示器尺寸来限制光标的位置,因为我之前是随机移动光标。

这是我的第一个尝试:

max_x = 10
max_y = 40
def limitXandY(x_arg, y_arg):
    # 预期输出长度为2的整数元组
    return x_arg, y_arg if x_arg < max_x and y_arg < max_y else max_x, max_y

运行代码时,我没有得到预期的输出。

print(limitXandY(5, 19)) # (5, 19, 40) => (x_arg, y_arg, max_y)
x, y = limitXandY(5, 19) # ValueError: too many values to unpack (expected 2)
print(limitXandY(50, 100)) # (50, 10, 40) => (x_arg, max_x, max_y)
x, y = limitXandY(50, 100) # ValueError: too many values to unpack (expected 2)

如你所见,我的方法返回长度为3的元组,而不是2。如果三元运算符在if语句中执行,我会得到期望的输出以及else语句的最后一个值,如果运算符在else语句中执行,我会得到if语句的第一个值作为方法输出元组的第一个值。

我已经找到了一个解决方法,使用括号,但这并不完全满足我,我想理解为什么这个三元运算符会这样行为。

解释是有帮助的!

英文:

While playing around with pyautogui I decided to make a method to limit the position of my cursor depending on the size of my monitor, since I was moving my cursor randomy.

This is what my first attempt looked like.

max_x = 10
max_y = 40
def limitXandY(x_arg, y_arg):
    # expected to outputs a tuple of integers with length 2
    return x_arg, y_arg if x_arg &lt; max_x and y_arg &lt; max_y else max_x, max_y

When running the code I did not get the expected output.

print(limitXandY(5, 19)) # (5, 19, 40) =&gt; (x_arg, y_arg, max_y)
x, y = limitXandY(5, 19) # ValueError: too many values to unpack (expected 2)
print(limitXandY(50, 100)) # (50, 10, 40) =&gt; (x_arg, max_x, max_y)
x, y = limitXandY(50, 100) # ValueError: too many values to unpack (expected 2)

As you can see above, my method returns a tuple of length 3 instead of 2. If the ternary operator goes in the if statement, I get the desired output plus last value of the else statement and if the operator returns in the else statement, I get the first value of the if statement as the first value of the methods output tuple.

I have found a work around using parentheses, but this doesn't really satisfy me and I would like to understand why this ternary operator acts like this.

def correctedLimitXandY(x_arg, y_arg):
    # expected to output a tuple of tuple with length 1
    # inner tuple should containt integers of length 2
    return (x_arg, y_arg) if x_arg &lt; max_x and y_arg &lt; max_y else (max_x, max_y)

print(correctedLimitXandY(5, 19)) # (5, 19) =&gt; (x_arg, y_arg)
x, y = correctedLimitXandY(5, 19) # no error
print(correctedLimitXandY(50, 100)) # (10, 40) =&gt; (max_x, max_y)
x, y = correctedLimitXandY(50, 100) # no error

Any explanations would be a help!

答案1

得分: 1

以下是要翻译的内容:

你的第一段代码等同于这个:

return x_arg, (y_arg if x_arg < max_x and y_arg < max_y else max_x), max_y

这是一个包含三个元素的元组。

这与解释器首先遇到逗号然后是条件有关。也就是说,它首先决定解释为一个元组,然后找到条件表达式。

英文:

Your first snippet of code is equivalent to this:

return x_arg, (y_arg if x_arg &lt; max_x and y_arg &lt; max_y else max_x), max_y

Which is a tuple of three elements.

This has to do with the fact that the interpreter first reaches the comma than the conditional. That is: it first decides is interpreting a tuple and then finds a conditional expression.

答案2

得分: 1

请注意,以下是您要翻译的文本:

"Any explanations would be a help!

While ternaries have a fairly low precedence, they're still considered an operator and thus binding 'tighter' than tuple literal, much like e.g.

a+b,c+d

is interpreted as

(a + b), (c + d)

not

a + (b, c) + d

When you write

x_arg, y_arg if x_arg < max_x and y_arg < max_y else max_x, max_y

Python will first 'resolve' <, then and, then if/else, and only after that does it resolve the tuples, so the result is:

x_arg, (y_arg if ((x_arg < max_x) and (y_arg < max_y)) else max_x), max_y

You can infer this from the full language grammar, specifically:
ebnf
expressions:
| expression (',' expression )+ [',']
| expression ','
| expression

expression:
| disjunction 'if' disjunction 'else' expression
| disjunction
| lambdef
"

英文:

> Any explanations would be a help!

While ternaries have a fairly low precedence, they're still considered an operator and thus binding "tighter" than tuple literal, much like e.g.

a+b,c+d

is interpreted as

(a + b), (c + d)

not

a + (b, c) + d

When you write

x_arg, y_arg if x_arg &lt; max_x and y_arg &lt; max_y else max_x, max_y

Python will first "resolve" &lt;, then and, then if/else, and only after that does it resolve the tuples, so the result is:

x_arg, (y_arg if ((x_arg &lt; max_x) and (y_arg &lt; max_y)) else max_x), max_y

You can infer this from the full language grammar, specifically:

expressions:
    | expression (&#39;,&#39; expression )+ [&#39;,&#39;] 
    | expression &#39;,&#39; 
    | expression

expression:
    | disjunction &#39;if&#39; disjunction &#39;else&#39; expression 
    | disjunction
    | lambdef

Here you can see that an expressions is a comma-separated sequence of expression, and each expression can be a ternary (if/else), therefore the language "resolves" ternaries (the inner structure) first.

huangapple
  • 本文由 发表于 2023年3月9日 18:53:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/75683607.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定