为什么Python3代码在Python2上运行?

为什么Python3代码在Python2上运行?,python,python-3.x,Python,Python 3.x,我创建了一个小的购物清单程序,设计用于在Python3上运行。我假设我的Mac电脑运行的是Python 3,并试图运行该文件。只要我用引号将输入字符串括起来,它似乎工作得很好,否则就会出现NameError。这在Python3中是不需要的 为什么代码会运行?我知道像print()这样的函数在Python2中的编写方式不同,所以为什么它一开始就没有失败呢 #列表创建 购物清单=[] #帮助 def show_help(): 打印(“”) 在提示时将项目添加到列表中。 要结束列表,请键入“完成”。

我创建了一个小的购物清单程序,设计用于在Python3上运行。我假设我的Mac电脑运行的是Python 3,并试图运行该文件。只要我用引号将输入字符串括起来,它似乎工作得很好,否则就会出现NameError。这在Python3中是不需要的

为什么代码会运行?我知道像print()这样的函数在Python2中的编写方式不同,所以为什么它一开始就没有失败呢

#列表创建
购物清单=[]
#帮助
def show_help():
打印(“”)
在提示时将项目添加到列表中。
要结束列表,请键入“完成”。
要查看列表,请键入“SHOW”。
要查看此帮助提示,请键入“帮助”。
""")
显示帮助()
#看法
def view_list():
打印(购物清单)
尽管如此:
新项目=输入(“>”)
如果new_item.upper()=“完成”:
打破
elif new_item.upper()=“帮助”:
显示帮助()
持续
elif new_item.upper()=“显示”:
查看列表()
持续
购物清单。附加(新项目)
打印(购物清单)

关于
打印
,Python3使其成为一个合适的函数,因此您必须用括号调用它。在Python2中,这些括号被解释为“分组”括号,而不是函数调用的开始,因此没有区别

Python2:
print(1+2)
表示对表达式进行求值
(1+2)
->
print 3


Python3:
print(1+2)
意味着计算表达式
1+2
,并将结果传递到函数
print
->
print(3)

您没有利用Python3的改进


因此,它可以在Python 2中运行(除了打印),因为它是完全有效的Python 2代码。但是,Python2中的
input
尝试对作为Python表达式输入的字符串求值;Python3中的等价物是
eval(输入(“>”)
。Python2应该始终使用
raw\u输入
,Python3通过摆脱旧的
input
行为并将
raw\u输入
重命名为
input
来实现这一点

对于
print
,关键字
print
后面的每个项目都是一个表达式,有效的表达式可以用括号括起来
print('hello')
只打印表达式
('hello')
的结果,该结果相当于未加密的字符串
'hello'
;因此,
print('hello')
print'hello'
是等效的


请注意,
print'hello'、
print'hello'、
并不等同;前者打印字符串
hello
,不带行尾,而后者打印单元素元组
(hello,)
。在Python3中,
print('hello',)
print('hello')
是相同的,因为函数调用的参数列表允许有一个被忽略的尾随逗号。

许多Python3代码在Python2中运行,因为Python是专门为实现这一点而设计的


print
是一种特殊情况,简单的
print
s单个变量在两种语言中做相同的事情,但更复杂的
print
s可能不会。这是怎么回事

在Python3中,
print(shopping\u list)
是对
print
函数的调用,该函数只有一个参数,
shopping\u list

在Python 2中,
print(shopping\u list)
是一个带有一个可打印值的print语句,
(shopping\u list)
,该值当然与
shopping\u list
的值相同。所以你得到了同样的结果

当然,当您
print(x,y)
(这很有效,但在Python2中打印一个2元组值而不是两个值)或
print(x,file=sys.stderr)
(这在Python2中是一个错误)时,情况就不是这样了


input
是另一种特殊情况。这一个不是为了兼容而设计的,你只是在这里走运而已。或者可能不走运

在Python 2中,
input()
执行
eval(raw\u input())
——也就是说,它接受您键入的内容并尝试将其作为Python源代码进行评估

在Python3中,
input()
执行Python2中的
raw\u input()
操作,也就是说,它只返回一个字符串

因此,代码在这两种情况下都能工作,尽管您必须在Python 2中键入
“DONE”
,而不是仅仅键入
DONE
——就像您必须在源代码中键入
“DONE”
。另外,当然,您可以在Python2中键入
\uuuuu import\uuuuu('os').system('rm-rf/')
,这会让您感到非常难过。(这就是为什么Python2的
输入在Python3中不存在的原因。)


如果您想知道为什么Python 3是这样设计的:

一旦确定需要一些向后的不兼容来修复20年的积压问题,就有一个讨论,关于“Python 3000”是否应该故意不兼容以大声破坏一切,或者尽可能兼容(但不再如此)以使迁移更容易

小组决定采用后者。这包括对Python2.6进行一些更改,使其更容易最终迁移到3.x,以及在Python3.0中做出一些设计决策,这些决策只是为了使从2.6迁移更容易

一旦Python3进入野外,这就是正确的选择。几乎所有人都感到惊讶的是,实际上编写“双版本”代码(借助于适配器库,如
six
)比编写可以通过
2to3
3to2
自动转换的代码更容易

所以他们走得更远。Python2.7添加了一些专为双版本代码设计的特性,并且他们继续添加类似于
u
string literal前缀的内容(在Python3中它不起任何作用,但它是一种确保无论在2.7还是3.4中运行都有Unicode字符串的方法)和