为什么Python 3代码在Python 2上运行呢?

时间:2018-03-13 17:09:30

标签: python python-3.x

我创建了一个小型购物清单程序,旨在在Python 3上运行。我假设我的Mac运行Python 3并尝试运行该文件。只要我用输入标记包围输入字符串,它似乎运行良好,否则我得到一个NameError。 Python 3中不需要这样做。

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

# List Creation
shopping_list = []

# Help
def show_help():
    print("""
Add items to the list when promted. 
To end the list type 'DONE'.
To view the list type 'SHOW'.
To view this help prompt, type 'HELP'.
""")

show_help()

# View
def view_list():
    print(shopping_list)

while True:
    new_item = input("> ")
    if new_item.upper() == 'DONE':
        break
    elif new_item.upper() == 'HELP':
        show_help()
        continue
    elif new_item.upper() == 'SHOW':
        view_list()
        continue
    shopping_list.append(new_item)
print(shopping_list)

4 个答案:

答案 0 :(得分:4)

许多Python 3代码在Python 2中运行,因为Python专门设计用于实现这一点。

print有点特殊情况 - 单个变量的简单print在两种语言中都做同样的事情,但更复杂的print可能不会。这是如何工作的?

在Python 3中,print(shopping_list)是使用单个参数print调用shopping_list函数。

在Python 2中,print(shopping_list)是一个打印语句,其中一个可打印,值为(shopping_list),当然与shopping_list的值相同。所以你得到同样的东西。

当你print(x, y)(有效,但在Python 2中打印单个2元组值而不是两个值)或print(x, file=sys.stderr)时(这是一个错误),这当然不是真的在Python 2)。

input是另一个特例。这个不是为了兼容,你在这里很幸运。或者也许不走运。

在Python 2中,input()执行eval(raw_input()) - 也就是说,它会输入您输入的内容,并尝试将其作为Python源进行评估。

在Python 3中,input()执行raw_input()在Python 2中所做的事情 - 也就是说,它只返回一个字符串。

因此,虽然您必须在Python 2中键入"DONE"而不仅仅是DONE,但代码类似于两者,就像您必须在源代码中键入"DONE"一样。另外,当然,您可以在Python 2中键入__import__('os').system('rm -rf /')并让自己非常难过。 (这就是Python 3中不存在Python 2的input。)

如果你问为什么Python 3是这样设计的:

一旦确定需要一些向后不兼容性来解决二十年的积压问题,就会讨论“Python 3000”是否应该故意不相容而吵闹一切,或尽可能兼容(但不是更多)使迁移变得更容易。

团队决定采用后者。这包括对Python 2.6进行一些更改,以便最终更容易迁移到3.x,以及Python 3.0中的一些设计决策,这些决策只能使从2.6迁移变得更容易。

一旦Python 3进入野外,结果证明这是正确的选择。几乎每个人都感到惊讶的是,编写“双版”代码(借助于six等适配器库)实际上比编写可以通过2to3和{{自动转换的代码编写代码更容易1}}。

所以他们走得更远了。 Python 2.7添加了一些专为双版本代码设计的功能,并且他们继续添加诸如3to2字符串文字前缀(在Python 3中什么都不做,但它确保你有Unicode的方法)。字符串,无论你运行在2.7或3.4)和u(允许Python 2 bytes.__mod__ - 格式化代码继续在Python 3中工作,如果你故意选择保留{{1 - 例如,解析HTTP,你所知道的是它是一些与ASCII兼容的字符集,直到你到达%标题。)

顺便说一句,对Python 2进行的“向前兼容性”更改之一是bytes的添加,它为您提供了Python 3风格的charset

答案 1 :(得分:1)

关于print,Python3使它成为一个正确的函数,所以你必须用括号调用它。在Python2中,这些括号被解释为"分组"括号而不是函数调用的开始,所以没有区别。

Python2:print (1 + 2)表示,评估表达式(1 + 2) - > print 3

Python3:print (1 + 2)表示评估表达式1 + 2并将结果传递给函数print - > print(3)

答案 2 :(得分:1)

它运行是因为它是完全有效的Python 2代码。但是,Python 2中的input尝试计算作为Python表达式输入的字符串; Python 3中的等价物是eval(input("> "))。 Python 2应始终使用raw_input,Python 3通过删除旧的input行为并将raw_input重命名为input来强制执行此操作。

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

但请注意,print 'hello',print('hello',) 不等同于此;前者打印字符串hello没有行结束,而后者打印单元素元组(hello,)。在Python 3中,print('hello',)print('hello')将是相同的,因为允许函数调用的参数列表具有被忽略的尾随逗号。

答案 3 :(得分:-3)

您没有利用Python 3的改进。

因此它在Python 2中起作用(除了打印)