1. 0x01 string

1.1. 编码

# unicode
chinese = '\u4e2d\u6587'
>>> print chinese.decode('unicode-escape')
中文

1.2. 基本操作

>>> "a" + "b"
'ab'
>>> "a" * 3
'aaa'
>>> ",".join(["a", "b", "c"])           # 合并多个字符串
'a,b,c'
>>> "a,b,c".split(",")                  # 按指定字符分割
['a', 'b', 'c']
>>> "a\nb\r\nc".splitlines()            # 按行分割
['a', 'b', 'c']
>>> "a\nb\r\nc".splitlines(True)        # 分割后,保留换行行符。
['a\n', 'b\r\n', 'c']
>>> "abc".startswith("ab"), "abc".endswith("bc")!       # 判断是否以特定子子串开始或结束。
True, True
>>> "abc".upper(), "Abc".lower()        # 大大小小写转换。
'ABC', 'abc'
>>> "abcabc".find("bc"), "abcabc".find("bc", 2)         # 可指定查找起始结束位置。
1, 4
>>> " abc".lstrip(), "abc ".rstrip(), " abc ".strip()   # 剔除前后空格。
'abc', 'abc', 'abc'
>>> "abc".strip("ac")                   # 可删除指定的前后缀字符。
'b'
>>> "abcabc".replace("bc", "BC")        # 可指定替换次数。
'aBCaBC'
>>> "a\tbc".expandtabs(4)               # 将 tab 替换成空格。
'a    bc'
>>> "123".ljust(5, '0'), "456".rjust(5, '0'), "abc".center(10, '*')     # 填充
'12300', '00456', '***abc****'
>>> "123".zfill(6), "123456".zfill(4)   # 数字填充
'000123', '123456'

1.3. 格式化

Python 提供了两种字符串格式化方方法

  1. %[(key)][flags][width][.precision]typecode

标记: - 左对齐, + 数字符号, # 进制前缀, 或者用用空格、0 填充。

>>> "%(key)s=%(value)d" % dict(key = "a", value = 10)       # key
'a=10'
>>> "[%-10s]" % "a"         # 左对齐
'[a         ]'
>>> "%+d, %+d" % (-10, 10)  # 数字符号
'-10, +10'
>>> "%010d" % 3             # 填充
'0000000003'
>>> "%.2f" % 0.1234         # 小小数位
'0.12'
>>> "%#x, %#X" % (100, 200) # 十十六进制、前缀、大大小小写
'0x64, 0XC8'
>>> "%s, %r" % (m, m)       # s: str(); r: repr()
'test..., <__main__.M object at 0x103c4aa10>'
  1. format 方方法支支持更多的数据类型,包括列表、字典、对象成员等

{field!convertflag:formatspec}

格式化规范: formatspec: [[fill]align][sign][#][0][width][.precision][typecode]

>>> "{key}={value}".format(key="a", value=10)   # 使用用命名参数
'a=10'
>>> "{0},{1},{0}".format(1, 2)                  # field 可多次使用用
'1,2,1'
>>> "{0:,}".format(1234567)                     # 千分位符号 
'1,234,567'
>>> "{0:,.2f}".format(12345.6789)               # 千分位,带小小数位。
'12,345.68'
>>> "[{0:<10}], [{0:^10}], [{0:*>10}]".format("a")! # 左中右对齐,可指定填充字符。
'[a       ], [    a     ], [*********a]'
>>> import sys
>>> "{0.platform}".format(sys)          # 成员
'linux2'
>>> "{0[a]}".format(dict(a=10, b=20))   # 字典
'10'
>>> "{0[5]}".format(range(10))          # 列表
'5'

另有 string.Template 模板可供使用用。该模块还定义了各种常见的字符序列。

>>> from string import letters, digits, Template
>>> letters`        # 字母母表
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
>>> digits          # 数字表
'0123456789'
>>> Template("$name, $age").substitute(name = "User1", age = 20)    # 模板替换。
'User1, 20'
>>> Template("${name}, $age").safe_substitute(name = "User1")       # 没找到值,不会抛出异常。
'User1, $age'

2. 0x02 字符串数字转换

二进制: ‘0b’ 开头 八进制: ‘0o’ 开头 十六进制: ‘0x’ 开头

  • 整数 <==> 字符串
# 十六进制
hex()       hex(number) -> string
> hex(10) ==> '0xa'

# 十进制
int()       int(x, base=10) -> int or long
> int('0b100', 0) ==> 4
> int('0b100', 2) ==> 4
> int('0x10', 16) ==> 16
> int('10', 16)   ==> 16

# 二进制
bin()       bin(number) -> string
> bin(4) ==> '0b100'

# 八进制
oct()       oct(number) -> string
> oct(17) ==> '021'

"{0:b}".format(4) ==> '100'
  • 整数 <==> 字节串

short:2字节, long:4字节

import struct

struct.unpack('<HH', bytes(b'\x01\x00\x00\x00')) ==> (1,0)
struct.unpack('<L', bytes(b'\x01\x00\x00\x00'))  ==> (1,)

struct.pack('<HH', 1,2)    ==> '\x01\x00\x02\x00'
struct.pack('<LL', 1,2)    ==> '\x01\x00\x00\x00\x02\x00\x00\x00'
  • 16进制串 <==> 字符串
'abc'.encode('hex')     ==> '616263'
binascii.b2a_hex('abc') ==> '616263'
binascii.hexlify('abc') ==> '616263'

'616263'.decode('hex')      ==> 'abc'
binascii.a2b_hex('616263')  ==> 'abc'
binascii.unhexlify('616263')==> 'abc'
  • 字符串 <==> 字节串


  • unicode

\u 后面是十六进制的Unicode码

+ prefix u

u‘中文’ ==> u'\u4e2d\u6587'

+ unicode 强制转换

要求 python文件中指定了对应的编码类型;并且对应的python文件的确是以该编码方式保存的
# -*- coding: utf-8 -*-

import sys

reload(sys)
sys.setdefaultencoding("utf-8")

s = unicode('中文')

>>> u'\u4e2d\u6587'
  • unicode <==> string

unicode ==> string : encode

string ==> unicode: decode

3. 0x03 编码

Python 2.x 默认采用用 ASCII 编码。为了完成编码转换,必须和操作系统字符编码统一一起来。

>>> import sys, locale
>>> sys.getdefaultencoding()            # Python 默认编码。
'ascii'
>>> c = locale.getdefaultlocale(); c    # 获取当前系统编码。
('zh_CN', 'UTF-8')
>>> reload(sys)                         # setdefaultencoding 在被初始化时被 site.py 删掉了。
<module 'sys' (built-in)>
>>> sys.setdefaultencoding(c[1])        # 重新设置默认编码。

str、unicode 都提供了 encode 和 decode 编码转换方方法。

  • encode: 将默认编码转换为其他编码。
  • decode: 将默认或者指定编码字符串转换为 unicode

标准库 codecs 模块用用来处理更复杂的编码转换

3.1. base64

  • characters set
ABCDEFGHIJKLMNOP
QRSTUVWXYZabcdef
ghijklmnopqrstuv
wxyz0123456789+/

4. 0x04 list

4.1. 基本操作

>>> []                          # 空列表
>>> ['a', 'b'] * 3   
['a', 'b', 'a', 'b', 'a', 'b']
>>> ['a', 'b'] + ['c', 'd']     # 连接多个列表
['a', 'b', 'c', 'd']
>>> list("abcd")                # 将序列类型或迭代器转换为列表
['a', 'b', 'c', 'd']
>>> [x for x in range(3)]       # 生生成器表达式
[0, 1, 2]

>>>l = list("abcbc")
>>>l[1:-1]                      # 切片
['b', 'c', 'b']
>>> l.count('b')                # 统计元素项
2
>>> l.index('b', 2)             # 从指定位置查找项,返回序号
3
>>> l.append('d')               # 追加元素
>>> l
['a', 'b', 'c', 'b', 'c', 'd']
>>> l.insert(1, 5)              # 指定位置插入元素
>>> l
['a', 5, 'b', 'c', 'b', 'c', 'd']
>>> l.extend(range(2))          # 合并列表
>>> l
['a', 5, 'b', 'c', 'b', 'c', 'd', 0, 1]
>>> l.remove('b')               # 移除第一个指定元素
>>> l
['a', 5, 'c', 'b', 'c', 'd', 0, 1]
>>> l.pop(0)                    # 弹出指定位置的元素(默认最后项)
'a'
>>> l
[5, 'c', 'b', 'c', 'd', 0, 1]

4.2. bisect 向有序列表中插入入元素

>>> import bisect
>>> l = ["a", "d", "c", "e"]
>>> l.sort()
>>> l
['a', 'c', 'd', 'e']
>>> bisect.insort(l, "b")
>>> l
['a', 'b', 'c', 'd', 'e']
>>> bisect.insort(l, "d")
>>> l
['a', 'b', 'c', 'd', 'd', 'e']

4.3. array

某些时候,可以考虑用用数组代替列表。 和列表存储对象指针不同,数组直接内嵌数据,既省了创建 对象的内存开销,又又提升了读写效率。

>>> import array
>>> a = array.array("l", range(10))     # 用用其他序列类型初始化数组。
>>> a
array('l', [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> a.tolist()                          # 转换为列表。
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> a = array.array("c")                # 创建特定类型数组。
>>> a.fromstring("abc")                 # 从字符串添加元素。
>>> a
array('c', 'abc')
>>> a.fromlist(list("def"))             # 从列表添加元素。
>>> a
array('c', 'abcdef')
>>> a.extend(array.array("c", "xyz"))   # 合并列表或数组。
>>> a
array('c', 'abcdefxyz')

5. 0x05 tuple

  • 只读对象,元组和元素指针数组内存是一一次性连续分配的
  • 虚拟机缓存 n 个元素数量小小于 20 的元组复用用对象

在编码中,应该尽可能用用元组代替列表。除内存复用用更高高效外,其只读特征更利于并行行开发

5.1. 基本操作:

>>> a = (4)             # 少了逗号,就成了普通的括号运算符了
>>> type(a)
<type 'int'>
>>> a = (4,)            # 这才是元组
>>> type(a)
<type 'tuple'>
>>> s = tuple("abcadef")! ! ! # 将其他序列类型转换成元组。
>>> s
('a', 'b', 'c', 'a', 'd', 'e', 'f')
>>> s.count("a")        # 元素统计。
2
>>> s.index("d")        # 查找元素,返回序号
4

5.2. 标准库 namedtuple

可用用名字访问元素项。

>>> from collections import namedtuple
>>> User = namedtuple("User", "name age")       # 空格分隔字段名,或使用用迭代器。
>>> u = User("user1", 10)
>>> u.name, u.age
('user1', 10)

其实 namedtuple 并不是元组,而而是利用用模板动态创建的自自定义类型

6. 0x06 dict

字典 (dict) 采用用开放地址法的哈希表实现

  • 自自带元素容量为 8 的 smalltable,只有 "超出" 时才到堆上额外分配元素表内存。
  • 虚拟机缓存 80 个字典复用用对象,但在堆上分配的元素表内存会被释放。
  • 按需动态调整容量。扩容或收缩操作都将重新分配内存,重新哈希
  • 删除元素操作不会立立即收缩内存

6.1. 创建字典

>>> {}              # 空字典
>>> {"a":1, "b":2}  # 普通构造方方式
>>> dict(a = 1, b = 2)          # 构造
{'a': 1, 'b': 2}
>>> dict((["a", 1], ["b", 2]))  # 用两个序列类型构造字典
{'a': 1, 'b': 2}
>>> dict(zip("ab", range(2)))   # 同上
{'a': 0, 'b': 1}
>>> dict(map(None, "abc", range(2)))    #同上
{'a': 0, 'c': None, 'b': 1}
>>> dict.fromkeys("abc", 1)     # 用序列作 key, 并提供默认的 value
{'a': 1, 'c': 1, 'b': 1}
>>> {k:v for k, v in zip("abc", range(3))}      # 使用用生生成表达式构造字典。
{'a': 0, 'c': 2, 'b': 1}

6.2. 基本操作

>>> d = {"a":1, "b":2}
>>> "b" in d            # 判断是否包含 key
True
>>> d = {"a":1, "b":2}  # 删除 k/v
>>> del d["b"]
>>> d
{'a': 1}
>>> d = {"a":1}
>>> d.update({"c": 3})  # 合并
>>> d
{'a': 1, 'c': 3}
>>> d = {"a":1, "b":2}
>>> d.pop("b")          # 弹出
>>> d
(2, {'a': 1})
>>> d = {"a":1, "b":2}
>>> d.popitem()         # 弹出 (key, value)
('a', 1)

# 默认返回值
>>> d = {"a":1, "b":2}
>>> d.get("c")              # 如果没有对应 key, 返回 None
None
>>> d.get("d", 123)         # 如果没有对应 key,返回缺省值。
>>> d.setdefault("a", 100)  # key 存在,直接返回 value。
1
>>> d.setdefault("c", 200)  # key 不存在,先设置,后返回。
200
>>> d
{'a': 1, 'c': 200, 'b': 2}

6.3. 迭代器操作

>>> d = {"a":1, "b":2}
>>> d.keys()
['a', 'b']
>>> d.values()
[1, 2]
>>> d.items()
[('a', 1), ('b', 2)]
>>> for k in d: print k, d[k]
a 1
b 2
>>> for k, v in d.items(): print k, v
a 1
b 2

对于大大字典,调用用 keys()、values()、items() 会构造同样巨大大的列表。建议用用迭代器替代,以减 少内存开销

>>> d = {"a":1, "b":2}
>>> d.iterkeys()
<dictionary-keyiterator object at 0x10de82cb0>
>>> d.itervalues()
<dictionary-valueiterator object at 0x10de82d08>
>>> d.iteritems()
<dictionary-itemiterator object at 0x10de82d60>
>>> for k, v in d.iteritems():
...    print k, v
a 1
b 2

6.4. 视图

要判断两个字典间的差异,使用用视图是最简便的做法。

>>> d1 = dict(a = 1, b = 2)
>>> d2 = dict(b = 2, c = 3)
>>> d1 & d2                 # 字典不支支持该操作。
TypeError: unsupported operand type(s) for &: 'dict' and 'dict'
>>> v1 = d1.viewitems()
>>> v2 = d2.viewitems()
>>> v1 & v2                 # 交集
set([('b', 2)]) 
>>> v1 | v2                 # 并集
set([('a', 1), ('b', 2), ('c', 3)])
>>> v1 - v2                 # 差集 (仅 v1 有,v2 没有的)
set([('a', 1)])
>>> v1 ^ v2                 # 对称差集 (不会同时出现在 v1 和 v2 中)
set([('a', 1), ('c', 3)])
>>> ('a', 1) in v1          # 判断
True

# 更新字典内容
>>> a = dict(x=1)
>>> b = dict(x=10, y=20)
39>>> a.update({k:b[k] for k in a.viewkeys() & b.viewkeys()})
>>> a
{'x': 10}

视图会和字典同步变更

>>> d = {"a": 1}
>>> v = d.viewitems()
>>> v
dict_items([('a', 1)])
>>> d["b"] = 2
>>> v
dict_items([('a', 1), ('b', 2)])
>>> del d["a"]
>>> v
dict_items([('b', 2)])

6.5. 扩展

当访问的 key 不存在时, defaultdict 自自动调用用 factory 对象创建所需键值对。factory 可以是任何无无参数函数或 callable 对象

>>> from collections import defaultdict
>>> d = defaultdict(list)       # key "a" 不存在,直接用用 list() 函数创建一一个空列表作为 value。
>>> d["a"].append(1)

>>> d["a"].append(2)
>>> d["a"]
[1, 2]

字典是哈希表,默认迭代是无无序的。如果希望按照元素添加顺序输出结果,可以用用 OrderedDict。

>>> from collections import OrderedDict
>>> d = dict()
>>> d["a"] = 1
>>> d["b"] = 2
>>> d["c"] = 3
>>> for k, v in d.items(): print k, v           # 并非非按添加顺序输出。
a 1
c 3
b 2
>>> od = OrderedDict()
>>> od["a"] = 1
>>> od["b"] = 2
>>> od["c"] = 3
>>> for k, v in od.items(): print k, v          # 按添加顺序输出。
a 1
b 2
c 3
>>> od.popitem()                                # 按 LIFO 顺序弹出。
('c', 3)
>>> od.popitem()
('b', 2)
>>> od.popitem()
('a', 1)

7. 0x07 set

集合 (set) 用用来存储无无序不重复对象。所谓不重复对象,除了不是同一一对象外,还包括 "值" 不能相同。集合只能存储可哈希对象,一一样有只读版本 frozenset。

判重公式: (a is b) or (hash(a) == hash(b) and eq(a, b))

在内部实现上,集合和字典非非常相似,除了 Entry 没有 value 字段。集合不是序列类型,不能像列表那样按序号访问,也不能做切片片操作

>>> s = set("abc")              # 通过序列类型初始化。
set(['a', 'c', 'b'])
>>> {v for v in "abc"}          # 通过构造表达式创建
set(['a', 'c', 'b'])
>>> "b" in s                    # 判断元素是否在集合中
True
>>> s.add("d")                  # 添加元素
>>> s
set(['a', 'c', 'b', 'd'])
>>> s.remove("b")               # 移除元素
>>> s
set(['a', 'c', 'd'])
>>> s.discard("a")              # 如果存在,就移除
>>> s
set(['c', 'd'])
>>> s.update(set("abcd"))       # 合并集合
>>> s
set(['a', 'c', 'b', 'd'])
>>> s.pop()                     # 弹出元素
'a'
>>> s
set(['c', 'b', 'd'])

7.1. 集合运算

>>> "c" in set("abcd")          # 判断集合中是否有特定元素
>>> set("abc") is set("abc")
False
>>> set("abc") == set("abc")    # 相等判断
True
>>> set("abc") != set("abc")    # 不等判断
False
>>> set("abcd") >= set("ab")    # 超集判断 (issuperset)
True
>>> set("bc") < set("abcd")     # 子集判断 (issubset)
True
>>> set("abcd") | set("cdef")   # 并集 (union)
set(['a', 'c', 'b', 'e', 'd', 'f'])
>>> set("abcd") & set("abx")    # 交集 (intersection)
set(['a', 'b'])
>>> set("abcd") - set("ab")     # 差集 (difference), 仅左边有,右边没有的
set(['c', 'd'])
>>> set("abx") ^ set("aby")     # 对称差集 (symmetric_difference)
set(['y', 'x'])                 # 不会同时出现在两个集合当中的元素
>>> set("abcd").isdisjoint("ab")    # 判断是否没有交集
False

7.2. 更新操作

>>> s = set("abcd")
>>> s |= set("cdef")        # 并集 (update)
>>> s
set(['a', 'c', 'b', 'e', 'd', 'f'])
>>> s = set("abcd")
>>> s &= set("cdef")        # 交集 (intersection_update)
>>> s
set(['c', 'd'])
>>> s = set("abx")
>>> s -= set("abcdy")       # 差集 (difference_update)
>>> s
set(['x'])
>>> s = set("abx")
>>> s ^= set("aby")         # 对称差集 (symmetric_difference_update)
>>> s
set(['y', 'x'])

集合和字典主键都必须是可哈希类型对象,但常用用的 list、dict、set、defaultdict、OrderedDict 都是不可哈希的,仅有 tuple、frozenset 可用用

>>> hash([])
TypeError: unhashable type: 'list'
>>> hash({})
TypeError: unhashable type: 'dict'
>>> hash(set())
TypeError: unhashable type: 'set'
>>> hash(tuple()), hash(frozenset())
(3527539, 133156838395276)

如果想把自自定义类型放入入集合,需要保证 hash 和 equal 的结果都相同才能去重

>>> class User(object):
...     def __init__(self, name):
...         self.name = name
>>> hash(User("tom"))           # 每次的哈希结果都不同
279218517
>>> hash(User("tom"))
279218521
>>> class User(object):
...    def __init__(self, name):
...        self.name = name
...    def __hash__(self):
...        return hash(self.name)
...    def __eq__(self, o):
...        if not o or not isinstance(o, User): return False
...        return self.name == o.name
>>> s = set()
>>> s.add(User("tom"))
>>> s.add(User("tom"))
>>> s
set([<__main__.User object at 0x10a48d150>])

results matching ""

    No results matching ""