python散装笔记——149: 从Python 2迁移到Python 3的不兼容性(六)

26: 编码/解码为十六进制不再可用

Python 2.x Version ≤ 2.7

"1deadbeef3".decode('hex')
# Out: '\x1d\xea\xdb\xee\xf3'
'\x1d\xea\xdb\xee\xf3'.encode('hex')
# Out: 1deadbeef3

Python 3.x Version ≥ 3.0

"1deadbeef3".decode('hex')
# Traceback (most recent call last):
# File "", line 1, in 
# AttributeError: 'str' object has no attribute 'decode'

b"1deadbeef3".decode('hex')
# Traceback (most recent call last):
# File "", line 1, in 
# LookupError: 'hex' is not a text encoding; use codecs.decode() to handle arbitrary codecs

'\x1d\xea\xdb\xee\xf3'.encode('hex')
# Traceback (most recent call last):
# File "", line 1, in 
# LookupError: 'hex' is not a text encoding; use codecs.encode() to handle arbitrary codecs

b'\x1d\xea\xdb\xee\xf3'.encode('hex')
# Traceback (most recent call last):
# File "", line 1, in 
# AttributeError: 'bytes' object has no attribute 'encode'

然而,正如错误消息所建议的那样,你可以使用codecs模块来实现相同的结果:

import codecs
codecs.decode('1deadbeef4', 'hex')
# Out: b'\x1d\xea\xdb\xee\xf4'
codecs.encode(b'\x1d\xea\xdb\xee\xf4', 'hex')
# Out: b'1deadbeef4'

注意,codecs.encode返回一个字节对象。要获得字符串对象,只需解码为ASCII:

codecs.encode(b'\x1d\xea\xdb\xee\xff', 'hex').decode('ascii')
# Out: '1deadbeeff'

27: 字典方法更改

在Python 3中,许多字典方法的行为与Python 2不同,许多方法也被移除了:has_keyiter*view*。作为d.has_key(key)的替代,现在必须使用key in d

在Python 2中,字典方法keysvaluesitems返回列表。在Python 3中,它们返回视图对象;视图对象不是迭代器,它们与迭代器有两点不同,即:

  • 它们有大小(可以使用len函数)
  • 它们可以多次迭代

此外,与迭代器一样,字典中的更改会反映在视图对象中。

Python 2.7从Python 3中回退了这些方法;它们分别可用作viewkeysviewvaluesviewitems。要将Python 2代码转换为Python 3代码,相应的形式是:

  • Python 2中的d.keys()d.values()d.items()应更改为list(d.keys())list(d.values())list(d.items())
  • Python 2中的d.iterkeys()d.itervalues()d.iteritems()应更改为iter(d)iter(d.values())iter(d.items())
  • 最后,Python 2.7中的方法调用d.viewkeys()d.viewvalues()d.viewitems()可以替换为d.keys()d.values()d.items()

将Python 2代码转换为Python 3代码时,有时会比较棘手,尤其是在迭代字典的键、值或项时进行修改。考虑以下代码:

d = {'a': 0, 'b': 1, 'c': 2, '!': 3}
for key in d.keys():
  if key.isalpha():
    del d[key]

代码看起来像是在Python 3中也会类似地工作,但在这里,keys方法返回的是视图对象,而不是列表,如果在迭代过程中字典大小发生变化,Python 3代码将因RuntimeError而崩溃:在迭代过程中字典大小发生了变化。解决方案当然是正确地写成for key in list(d)

同样,视图对象的行为与迭代器不同:不能在它们上使用next(),并且不能恢复迭代;相反,它会重新开始;如果Python 2代码将d.iterkeys()d.itervalues()d.iteritems()的返回值传递给一个期望迭代器而不是可迭代对象的方法,那么在Python 3中应该是iter(d)iter(d.values())iter(d.items())

28: 类布尔值

Python 2.x Version ≤ 2.7

在Python 2中,如果你想自己定义类的布尔值,你需要在你的类中实现__nonzero__方法。默认值为True

class MyClass:
  def __nonzero__(self):
    return False

my_instance = MyClass()
print bool(MyClass) # True
print bool(my_instance) # False

Python 3.x Version ≥ 3.0

在Python 3中,使用__bool__而不是__nonzero__

class MyClass:
  def __bool__(self):
    return False

my_instance = MyClass()
print(bool(MyClass)) # True
print(bool(my_instance)) # False

29: Python 2中hasattr函数的错误

在Python 2中,当属性引发错误时,hasattr会忽略该属性,返回False

class A(object):
  @property
  def get(self):
    raise IOError

class B(object):
  @property
  def get(self):
    return 'get in b'

a = A()
b = B()

print 'a hasattr get: ', hasattr(a, 'get')
# output False in Python 2 (fixed, True in Python 3)
print 'b hasattr get', hasattr(b, 'get')
# output True in Python 2 and Python 3

此错误已在Python 3中修复。因此,如果你使用的是Python 2,可以使用以下代码:

try:
  a.get
except AttributeError:
  print("no get property!")

或者使用getattr代替:

p = getattr(a, "get", None)
if p is not None:
  print(p)
else:
  print("no get property!")

相关文章

Python实现整数的进制转换

任务要求将十进制整数分别转换为二进制、八进制和十六进制,并将结果在控制台打印输出。任务分析Python提供了bin()、oct()、hex()等内置函数直接完成进制转换,但输出结果包含前缀(如0b)。...

Python中的进制转换函数详解

左手编程,右手年华。大家好,我是一点,关注我,带你走入编程的世界。公众号:一点sir,关注领取python编程资料在编程中,经常需要在不同的进制之间转换数值,尤其是二进制、八进制、十进制和十六进制。P...

Python中的十六进制与十进制的相互转换

十进制主要运用于日常生活当中,而八进制主要运用于电子技术行业,是为了配合二进制而使用的,二进制是机器能够识别的最直接语言,但是二进制位数太多,不方便记录,所以一般把二进制转化为八进制或十六进制。在这篇...

「调试」使用python与单片机进行通信

调试说明:环境:usb转ttl线一根,通信协议一份,STC系列单片机一个,电脑一台。功能:使用python发送16进制数据转换成字节流数据发给单片机,单片机返回16进制数据后转10进制(本次测试是获取...

逐浪字体大师的UNI转码之Excel将十六进制转换成十进制的方法

最近在做字体大师,一款可以快速通过网页进行字体设计,从而生成字体的开放工具,部署于v.ziti163.com,效果如下:在这里插入图片描述因为其中C#需要调用字符码,其读取的是10进制,而字体的uni...