丰富的序列

内置序列概览

  • 容器序列(container sequences): list, tuple, collections.deque
    • 存放对象的引用
  • 扁平序列(flat sequences):str, bytes, array.array
    • 在自己的内存空间存储内容值
  • Python Object in memory has a header with metadata
    • float: ob_refcnt, ob_type, ob_fval
  • 可变序列(Mutable sequences): list, bytearray, array.array, collections.deque
  • 不可变序列(Immutable sequences): tuple, str, bytes

列表推导式/生成器表达式

  • List Comprehensions(listcomps) and Generator Expressions(genexps)

    In Python code, line breaks are ignored inside pairs of [], {}, or (). So you can build multiline lists, listcomps, tuples, dictionaries, etc., without using the \ line continuation escape, which doesn’t work if you accidentally type a space after it.

  • “Walrus operator” := with local scope
>>> x = 'ABC'
>>> codes = [ord(x) for x in x]
>>> x 
'ABC'
>>> codes [65, 66, 67]
>>> codes = [last := ord(c) for c in x]
>>> last 
67
>>> c
	File "<stdin>", line 1, in <module> 
NameError: name 'c' is not defined
  • some useful tips For :=a
    • Links:PEP 572—Assignment Expressions
      # INVALID
      x := 0
      # Valid alternative
      (x := 0)
      # INVALID
      x = y := 0
      # Valid alternative
      x = (y := 0)
      # Valid
      len(lines := f.readlines())
      # Valid
      foo(x := 3, cat='vector')
      # INVALID
      foo(cat=category := 'vector')
      # Valid alternative
      foo(cat=(category := 'vector'))
      
  • Differences between assignment expressions and assignment statements
-   Multiple targets are not directly supported:
    x = y = z = 0  # Equivalent: (z := (y := (x := 0)))
    
-   Single assignment targets other than a single `NAME` are not supported:
    
    # No equivalent
    a[i] = x
    self.rest = []
    
-   Priority around commas is different:
    
    x = 1, 2  # Sets x to (1, 2)
    (x := 1, 2)  # Sets x to 1
    
-   Iterable packing and unpacking (both regular or extended forms) are not supported:
    
    # Equivalent needs extra parentheses
    loc = x, y  # Use (loc := (x, y))
    info = name, phone, *rest  # Use (info := (name, phone, *rest))
    
    # No equivalent
    px, py, pz = position
    name, phone, email, *other_info = contact
    
-   Inline type annotations are not supported:
    
    # Closest equivalent is "p: Optional[int]" as a separate declaration
    p: Optional[int] = None
    
-   Augmented assignment is not supported:
    total += tax  # Equivalent: (total := total + tax)
  • 列表推导式与map/filter比较,有时候可读性更强,性能方面相差不大
>>> symbols = '$¢£¥€¤'
>>> beyond_ascii = [ord(s) for s in symbols if ord(s) > 127]
>>> beyond_ascii
[162, 163, 165, 8364, 164]
>>> beyond_ascii = list(filter(lambda c: c > 127, map(ord, symbols)))
>>> beyond_ascii
[162, 163, 165, 8364, 164]
  • 生成器表达式通过迭代器逐个产生项,与而不是构建个列表提供给其他构造函数
line_list = ['  line 1\n', 'line 2  \n', ' \n', '']
# Generator expression -- returns iterator
stripped_iter = (line.strip() for line in line_list)
# List comprehension -- returns list
stripped_list = [line.strip() for line in line_list]
  • array
    • array.typecodes: 'bBuhHiIlLqQfd'
    • the type of objects stored in them is constrained

元组

  • Tuples hold records: each item in the tuple holds the data for one field, and the position of the item gives its meaning.
    • print with operator ‘%’ can unpack tuple
  • Tuples as Immutable Lists:
    • When you see a tuple in code, you know its length will never change.
    • A tuple uses less memory than a list of the same length, and it allows Python to do some optimizations.
  • We can use hash to determine explicitly a tuple has a fix value
def fixed(o):
    try:
        hash(o)
    except TypeError:
        return False
    return True

tf = (10, 'alpha', (1, 2))  # Contains no mutable items
tm = (10, 'alpha', [1, 2])  # Contains a mutable item (list)
fixed(tf) # True
fixed(tm) # False

序列和可迭代对象拆包

  • parallel assignment
>>> lax_coordinates = (33.9425, -118.408056)
>>> latitude, longitude = lax_coordinates # unpacking
>>> latitude 
>>> 33.9425

>>> divmod(20, 8) 
(2, 4)
>>> t = (20, 8)
>>> divmod(*t)
(2, 4)
>>> quotient, remainder = divmod(*t)
>>> quotient, remainder 
(2, 4)

>>> import os
>>> _, filename = os.path.split('/home/luciano/.ssh/id_rsa.pub')
filename 'id_rsa.pub'
  • In Python, *args grab arbitrary excess arguments, it can appear in any position
    • It can be used in function arguments
>>> a, b, *rest = range(5)
>>> a, b, rest 
(0, 1, [2, 3, 4])
>>> a, *b, rest = range(4)
>>> a, b, rest 
(0, [1, 2], 3)
>>> a, b, *rest = range(2)
>>> a, b, rest 
(0, 1, [])
>>> *a, = range(5)
>>> a
[0, 1, 2, 3, 4]

>>> *range(4), 4
(0, 1, 2, 3, 4)

A Small Puzzle

Example 2-16. A riddle

>>> t = (1, 2, [30, 40])
>>> t[2] += [50, 60]

What happens next? Choose the best answer: A. t becomes (1, 2, [30, 40, 50, 60]). B. TypeError is raised with the message ‘tuple’ object does not support item assignment. C. Neither. D. Both A and B.

>>> dis.dis('s[a] += b')
  1           0 LOAD_NAME                0 (s)
              2 LOAD_NAME                1 (a)
              4 DUP_TOP_TWO
              6 BINARY_SUBSCR # Put the value of s[a] on TOS (Top Of Stack)
              8 LOAD_NAME                2 (b)
             10 INPLACE_ADD # Perform add
             12 ROT_THREE
             14 STORE_SUBSCR # Assign
             16 LOAD_CONST               0 (None)
             18 RETURN_VALUE

List.sort与内置函数sorted

  • List.sort method sorts a list in place without making a copy(use Timsort)
  • The built-in function sorted creates a new list and returns it
  • Accept both reverse and key(function)

When a List Is Not the Answer

  1. If a list only contains numbers, an array.array is a more efficient replacement. Arrays support all mutable sequence operations (including .pop, .insert, and .extend), as well as additional methods for fast loading and saving, such as .frombytes and .tofile.
  2. The built-in memoryview class is a shared-memory sequence type that lets you handle slices of arrays without copying bytes.
>>> from array import array
>>> octets = array('B', range(6))
>>> m1 = memoryview(octets)
>>> m1.tolist()
[0, 1, 2, 3, 4, 5]
>>> m2 = m1.cast('B', [2, 3])
>>> m2.tolist() 
[[0, 1, 2], [3, 4, 5]]
>>> m3 = m1.cast('B', [3, 2])
>>> m3.tolist() 
[[0, 1], [2, 3], [4, 5]]
>>> m2[1,1] = 22
>>> m3[1,1] = 33 
>>> octets 
array('B', [0, 1, 2, 33, 22, 5])
  1. NumPy implements multidimensional, homogeneous arrays and matrix types that hold not only numbers but also user-defined records, and provides efficient element-wise operations.
  2. Deques and Other Queues