Python 数据类型详解系列(1) - 数字和字符串


Life is short!

Python 作为一门强大易用的语言,内置了多种数据类型,有基本类型:int、long、float、string等,有集合类型:tuple、list、set、dict等,除此之外标准库还自带了多种数据结构:OrderedDict、deque、heapq、bisect等。

数据类型的知识点还是比较琐碎和繁多的,所以计划写成一个小系列,本篇先讲解基本的数字(int、long 和 float)和字符串(unicode 和 str)。

本文 ice 将会以 Python 2.7 为主,也会对 Python 3 进行一些说明,尽量将常见的用法和错误都列举出来,希望读者读完之后可以有所收获,能对读者在日常的工作实战中有所帮助。

基本类型

int / long / float

数字类型大家经常用,但是依然有几点需要注意的:

int 与 long 一般无需太关注,int 无法表达的数会自动转换为 long,所以在对整数的类型判断时需要考虑这种特例。

import sys
sys.maxint  # 9223372036854775807
a = sys.maxint
type(a)  # int
a += 1
type(a)  # long

isinstance(a, (int, long))  # True

float 默认精度为小数点后 13 位,所以当格式化 float 超过 13 位小数的时候,仍然可以显示,但是显示的数字毫无意义。

'%.13f' % (5000.0/3)  # '1666.6666666666667'
'%.30f' % (5000.0/3)  # '1666.666666666666742457891814410686'

float 有表示精度的问题,导致会出现一些错误的结果,这个与其他语言一致,主要是因为二进制无法精确地表示某些小数导致,可以参考官方文档

0.1 + 0.2  # 0.30000000000000004

针对 float 的问题,可以考虑采用 decimal 模块。

import decimal
# prec 表示精度,默认为 28,包含 28 个数字,包含整数部分
decimal.getcontext()  # Context(prec=28, rounding=ROUND_HALF_EVEN, Emin=-999999999, Emax=999999999, capitals=1, flags=[], traps=[InvalidOperation, DivisionByZero, Overflow])
# 修改精度
decimal.getcontext().prec = 30

decimal.Decimal(5000.0)/3  # Decimal('1666.666666666666666666666667')

decimal.Decimal(0.1) + decimal.Decimal(0.2)  # Decimal('0.30000000000000001665334536937734810635447502136230')

str / unicode

Python 2.x 的一个字符串编码问题,是初学者的一个痛,主要是由于有两种字符串的类型存在导致。

unicode 是一种统一的编码方式,str 是带有编码的二进制字符串,可以用来保存二进制。

为了避免中文编码问题,有两条好的实践:在 Python 内部尽量全部使用 unicode;在与外部交互的时候尽量使用 utf-8 编码的 str。这样可以有效地解决编码问题,各类问题的排查也是从这两类问题开始。

一点说明:Python 的单引号和双引号完全等价,就是说 Python 没有 char 这样的类型,只能用单个字符的字符串来表示。

a = u'中国'
repr(a)  # u'\u4e2d\u56fd'

# 在某些类库中可能会获得下面的字符串,这个很可能是因为使用 latin-1 来转换为了 unicode 导致的
a = u'\xe4\xb8\xad\xe5\x9b\xbd'
unicode('中国', 'latin-1')  # u'\xe4\xb8\xad\xe5\x9b\xbd'

# 解决方法是用 latin-1 编码 encode 回去,在 decode 为 utf-8 即可
a.encode('latin-1')  # '\xe4\xb8\xad\xe5\x9b\xbd'
a.encode('latin-1').decode('utf-8')  # u'\u4e2d\u56fd'

字符串定义的时候带有 u 前缀,表示为 unicode 类型。

在 Python 3 中默认即为 unicode,定义 str 需要使用 b 前缀;在 Python 2 中默认是 str,定义 unicode 需要使用 u 前缀。

另外还有 r 前缀,表示里面 \ 无需转移,一般在正则表达式的时候使用,减少 \ 的输入次数,较为方便。

多行字符串的定义有两种方式,一种是使用 “”“<str>””” 来定义,还有一种使用多个单行字符串拼接。

multi_lines = """This is a test.
This is second line."""

# 这里使用来括号,而非 \ 来换行,代码更容易阅读
multi_lines = ("This is a test.\n"
               "This is second line.")

# 下面用 \ 来换行的会影响代码阅读的流畅度,不推荐使用
multi_lines = "This is a test.\n"\
              "This is second line."

字符串不要进行频繁的拼接操作,会直接影响性能,可以考虑采用 list 来保存,最后 join 完成拼接。这点在 Java 中会使用 StringBuffer 来进行拼接,JVM 还为此做了针对性的优化,Python 中我们需要自己来做优化。

未完待续

下一篇,ice 将会带领大家来内置集合类型(tuple、list、set、dict)的讲解,欢迎大家讨论和补充。


如果觉得文章对您有帮助,用微信请作者喝杯咖啡吧!这样他会更有动力,分享更多更好的知识!

wechat赞赏