为什么Python赋值不返回值?

max*_*max 46 python language-design python-3.x

为什么Python赋值语句而不是表达式?如果它是一个表达式,它返回赋值中右侧的值,那么在某些情况下它会允许更简洁的代码.有什么问题我看不到吗?

例如:

# lst is some sequence
# X is come class
x = X()
lst.append(x)
Run Code Online (Sandbox Code Playgroud)

可以改写为:

lst.append(x = X())
Run Code Online (Sandbox Code Playgroud)

嗯,确切地说,上述方法不起作用,因为x它将被视为关键字参数.但另一对parens(或关键字参数的另一个符号)将解决这个问题.

Lau*_*ves 42

有许多人认为赋值是表达式,特别是在像Python这样的语言中,条件允许的任何值(不仅仅是某些布尔类型的值)都容易出错.据推测,Guido是那些有这种感觉的人.经典错误是:

if x = y: # oops! meant to say ==
Run Code Online (Sandbox Code Playgroud)

Python中的情况也比使用C语言更复杂,因为在Python中,对变量的第一个赋值也是它的声明.例如:

def f():
    print x

def g():
    x = h()
    print x
Run Code Online (Sandbox Code Playgroud)

在这两个函数中," print x"行执行不同的操作:一个引用全局变量x,另一个引用局部变量x.因为作业,xin g是本地的.如果有可能将赋值放在一个更大的表达式/语句中,这可能会更加混乱(比现在已经多了).

  • @Glenn:Python没有编译器来警告你,没有像这样的"几乎语法错误"的概念. (15认同)
  • "= vs =="的东西是红鲱鱼.自从编译器学会如何警告它以来,多年来它一直不是C/C++中的实际问题.我已经使用这两种语言超过十年了,我不记得上一次被我咬了. (10认同)
  • @Lennart:试图阻止初学者犯下初学者的错误是徒劳的,而不是 - 至少不是自己,而是以牺牲别的东西 - 一个好的设计理由; 并且"我们不能通过警告来做到这一点,因为我们的警告系统不够发现"指出警告系统或文档的问题 - 你没有围绕警告系统设计一种语言,你做了相反的事情. (7认同)
  • @Glenn:但是因为它在运行时使用*它不能以相同的意义警告这些事情.C中的编译器警告有点"几乎是语法错误",它说"你真的确定要这个吗".这个概念没有Python等价物.它是正确的,还是语法错误.Python试图避免支持导致新手犯错误的事情.:-) (4认同)
  • 重点是在单词的正常使用中没有"编译时间",因为编译是在运行期间按需完成的.这是我一直在这里指出的差异.重复自己变得无聊,所以我现在要停下来. (4认同)
  • @Lennart:当然Python有一个编译器; 每次加载新代码时都会使用它.Python还有一个警告机制,编译器使用它.(我认为它甚至不重要.即使我被困在MSVC中并没有发出警告,我也没有任何麻烦.这似乎是人们刚刚作为初学者出现的那种问题,然后经历他们的职业生涯,认为这是一个巨大的问题.扼杀使用尤达条件的人是合法的,对吗?) (2认同)
  • @max:这个假设是错误的。“导入”是动态完成的,这被认为是一个功能。请参阅“os”库的 Python 代码以及它如何通过根据系统架构导入不同的模块来实现“os.path”。我认为伦纳特的观点终于在他最后的评论中变得清晰起来。 (2认同)

Gle*_*ard 16

现实世界的答案:不需要它.

您在C中看到的大多数情况都是因为错误处理是手动完成的:

if((fd = open("file", O_RDONLY)) == -1)
{
    // error handling
}
Run Code Online (Sandbox Code Playgroud)

类似地,对于写入许多循环的方式:

while(i++ < 10)
    ;
Run Code Online (Sandbox Code Playgroud)

这些常见情况在Python中以不同方式完成.错误处理通常使用异常处理; 循环通常使用迭代器.

反对它的论点不一定是惊天动地,但它们与它在Python中并不那么重要的事实相称.

  • 有时您可能需要诸如`while(x [k] + = 1)<= limit:...`之类的东西; 你可以在没有作为表达式的赋值的情况下重写它,但这需要一个非平凡的重组. (3认同)

ben*_*min 11

您可以期望(x := y)在不久的将来版本的python中实现对表达式的支持.Guido最近在2018年7月接受了一项PEP 572提案,以支持python中的赋值表达式.(之前也有过提案,例如撤回的PEP 379.)

回想一下,直到版本3,lst.append(x := X())它也是一个陈述而不是表达.

注:该语句print分配相同的值到多个目标(或者更确切地说,多目标列表,因为拆包也是允许的)已经长期支持Python,但作为一种特殊的实现语法,而不是通过链接连续分配的子表达式.(实际上,执行个人作业的顺序是相反的.)

  • 您应该只编辑文本以包含当前信息,而无需 **更新** 部分:) (2认同)
  • @huggie同样的方式``(a*2表示b中的a)a``和其他化合物的作用.整个``a = b = 3``是*one*赋值语句,而不是两个表达式,如``a =(b:= 3)``.与容器文字相比,容器文字也是任意元素大小 - "(a,b,3)``与``(a,(b,3))``不一样. (2认同)
  • 3.8 就会出现。 (2认同)

Pet*_*ell 7

我认为这是为了防止某些经典错误而故意在Guido的部分.例如

if x = 3: print x

当你真正想说的时候

if x == 3: ...

我不同意有次我希望它的工作,但我也想念{}周围的代码块,那肯定是不会改变的.