小能豆

准备从 Python 2.x 转换为 3.x

py

我们现在都知道(我希望如此),Python 3 正在慢慢开始取代 Python 2.x。当然,大多数现有代码最终移植还需要很多年,但我们现在可以在 2.x 版本代码中做一些事情,让切换更容易。

显然,了解3.x 中的新功能会有所帮助,但是我们现在可以做些什么来让即将到来的转换更加轻松(以及在需要时更容易将更新输出到并发版本)?我特别考虑了我们可以用哪些行来开始我们的脚本,这将使早期版本的 Python 更类似于 3.x,尽管其他习惯也是受欢迎的。

我能想到的添加到脚本顶部的最明显的代码是:

from __future__ import division
from __future__ import print_function
try:
    range = xrange
except NameError:
    pass

我能想到的最明显的习惯是 "{0} {1}!".format("Hello", "World") 字符串格式化。

还有其他什么好习惯可以养成吗?


阅读 14

收藏
2024-11-12

共1个答案

小能豆

很棒的想法!为兼容 Python 3 而准备 Python 2.x 代码有助于简化最终的迁移,还有其他几种方法可以使这种过渡更加顺利。除了您的建议外,这里还有一些其他更改和最佳实践:

1. 导入兼容性功能

除了division和 之外print_function,还请考虑以下其他__future__导入:

from __future__ import unicode_literals  # Makes string literals Unicode by default
from __future__ import absolute_import   # Enforces explicit relative imports
  • Unicode 文字:这使得字符串文字的行为类似于 Python 3 的 Unicode 字符串,这可以避免以后出现编码问题。
  • 绝对导入:这可以防止隐式相对导入,鼓励使用与 Python 3 兼容的更清晰的导入语句。

2. 使用sixfuture

six和库future提供了用于编写在 Python 2 和 3 上均可运行的代码的实用程序。例如,six提供six.moves处理更改位置的导入的功能:

from six.moves import range  # Replaces xrange with range in both versions
from six.moves import input  # Maps raw_input to input in Python 2, or uses input in Python 3

3. 编写兼容性友好的代码

  • 字符串格式化:正如您所提到的,更喜欢str.format()语法。但更进一步,如果使用 Python 3.6 或更高版本,请考虑使用 f 字符串。否则,请使用命名占位符格式化字符串,以便清晰易懂:

"{greeting}, {name}!".format(greeting="Hello", name="World")

  • items()用 代替进行迭代iteritems()

for key, value in my_dict.items(): # Do something

使用items()overiteritems()可确保兼容性,但要注意大型词典的内存。在这里six也有six.iteritems帮助。

4.明确处理文本和二进制数据

Python 3 对文本(Unicode)和二进制数据(字节)有区别地对待,因此最好做好准备:

# Explicitly encode/decode text for file or network operations
text = "hello"
binary_data = text.encode('utf-8')
decoded_text = binary_data.decode('utf-8')

5.io.open用于文件处理

在 Python 2 中,io.open提供与 Python 3 兼容的文件处理和编码支持:

import io
with io.open('file.txt', 'r', encoding='utf-8') as f:
    contents = f.read()

6.next()作为函数使用

为了准备 Python 3 的next()功能并避免混淆,请始终next()明确使用:

my_iter = iter([1, 2, 3])
first_item = next(my_iter)

7. 定义__bool__而不是__nonzero__

在 Python 3 中,定义真实性的__bool__替换为:__nonzero__

class MyClass:
    def __bool__(self):
        return True

    __nonzero__ = __bool__  # For Python 2 compatibility

8.处理异常语法变化

Python 3 用于as异常:

try:
    # Some operation
except SomeException as e:
    print(e)

9.避免None与其他类型进行比较

在 Python 3 中,None与非 None 值(例如None < 5)进行比较会引发错误,因此请使用is Noneis not None

if my_var is None:
    # Do something

10. 使用__metaclass__Python 3 类的语法(可选)

对于需要元类的类,请使用与 Python 2 和 3 兼容的语法:

class MyClass(object, metaclass=MyMetaClass):
    pass

或者,你可以__metaclass__在 Python 2 中的类顶部设置:

class MyClass:
    __metaclass__ = MyMetaClass

过渡期的其他良好习惯

  1. 避免print语句:始终将其用作print()函数。
  2. 避免隐式整数除法//如果需要,请始终使用整数除法。
  3. __init__小心使用super():始终使用super(ClassName, self).__init__()以确保与旧式和新式类的兼容性
  4. 避免依赖字典顺序:Python 3.7+ 保证字典中的插入顺序,但不要依赖早期版本。

这些策略将使您的代码具有更好的 Python 3 兼容性,并有助于使最终的过渡变得更加容易。

2024-11-12