流畅的python笔记

1、collection.nametuple是一个工厂函数,可以很方便地定义一种数据类型,它具备tuple的不变性,又可以根据属性来引用,使用十分方便,而不需要重新定义一个类那么麻烦。

#nametuple的属性和方法
City._fields #('name', 'country', 'population', 'coordinates')

_make(iterable)  #类方法, 对可迭代对象进行实例化
_asdict()  #实例方法,把nametuple以collections.OrderedDict的形式返回,使其友好呈现

2、定义类的一些技巧

import collections
Card = collections.namedtuple('Card', ['rank', 'suit']) #避免自定义class的麻烦

class FrenchDeck:
  ranks = [str(n) for n in range(2,11)] + list('JQKA')
  suits = 'spades diamonds clubs hearts'.split()
  
  def __init__(self):
    self._cards = [Card(rank,suit) for suit in self.suits
                  for rank in self.ranks]
    
  def __len()__:
    return len(self._cards)
  
  def __getitem__(self, position): #实现该方法即实现可迭代,因此in运算符可以使用
    return self._cards[position] #支持切片

3、

from math import hypot

class Vector:
  def __init__(self, x=0, y=0):
    self.x = x
    self.y = y
  
  def __repr__(self): #把一个对象用字符串的形式表达出来,__repr__比__str__是更好的选择,__str__是给终端看的,__repr__调试用
    return 'Vector(%r, %r)' % (self.x, self.y)
  
  def __abs__(self):
    return hypot(self.x, self.y)
  
  def __bool__(self):
    return bool(abs(self)) # return bool(self.x, self.y)更高效,省掉abs到__abs__的转化
  
  def __add__(self, other):
    x = self.x + other.x
    y = self.y + other.y
    return Vector(x, y)
  
  def __mul__(self, scalar):
    return Vector(self.x * scalar, self.y * scalar)

还有一系列的特殊方法。

4、为什么len不是普通的方法?运行更快。

5、

容器序列(存放不同类型):list, tuple, collections.deque

扁平序列(存放单类型):  str, bytes, bytearray, memoryview, array.array

6、列表推导

codes = [ord(symbol) for symbol in symbols]

同filter和map的比较,列表推导都能做,而且不用lambda

beyond_ascii = [ord(s) for s in symbols if ord(s)>127]
beyond_ascii = list(filter(lambda c:c>127, map(ord, symbols)))

7、生成器表达式:逐个生成,节省内存,注意是()

tuple(ord(symbol) for symbol in symbols)

8、可以使用*运算符把一个可迭代对象拆开作为函数的参数。

t = (20, 8) #可迭代对象
divmod(*t) 

还可以使用*来获取不确定的参数

a, b, *rest = range(5) #(0,1,[2,3,4])

9、二维的numpy可以使用二维切片 [ m:n, k:l ],如果x是四维数组,x[ i, ...] 就是 x[i, :, :, : ]。

如果赋值的对象是一个切片,那么赋值右边必须是个可迭代的对象。

l[ 2:5 ] = [100] #
l[ 2:5 ] = 100   #

10、

board = [ ['_'] * 3 for i in range[3]]
weird_board = [ ['_'] * 3] *3 #单点赋值会修改多个点,原因是列表内的3个引用指向同一个对象

11、

*= 在可变序列上不会改变序列ID,但在不可变的序列(如tuple)会改变ID,原因是对不可变序列进行重复拼接效率很低,因为每次都要把旧对象的元素赋值到新对象里,再追加元素。

12、一个谜题

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

#结果有两个:
#元组不可赋值,会抛出异常,还会把t改变了:
#t变成 ( 1, 2, [30, 40, 50, 60] )

鉴于上面的情况,建议:不要把可变对象放在元组里面,增量赋值不是一个原子操作(像上面的例子)

13、list.sort 返回None,sorted返回新建的排序列表

14、使用bisect来管理已排序的序列。

#该模块不会影响原排序
bisect.insort() #插入并改变原序列
bisect.bisect() #插入但不改变原序列
bisect.bisect_left() #插在重复数字的左边,返回插入位置,不改变原序列

15、

存放大量浮点数是,数组(array)的效率更高。

检查一个元素是否出现在一个集合中,set更合适。

如果只包含数字的列表,那么array.array比list更高效。数组还提供从文件读取和存入文件的更快的方法,如.frombytes和.tofile。

pickle.dump的处理速度和array.tofile一样快。

16、内存视图memoryview

让用户在不复制内容的情况下操作同一个数组的不同切片。

17、dict,defaultdict,OrderedDict

defaultdict在未找到的元素时,补上默认构造。(注意被__getitem__调用的__missing__方法)

dict.setdefault的妙用(一句顶三句):

index.setdefault(word, []).append(location) #检索word,不存在则返回[ ],然后在该[ ]后添加位置。 

if key not in my_dict:
  my_dict[key] = []
my_dict[key].append(new_value)

18、

collection.OrderedDict #键值保持顺序
collection.ChainMap #存储不同的映射对象
collection.Counter #对键值进行统计
collection.most_common #对键值进行统计,返回常见的前几名

19、使用MappingProxyType来获取字典的只读实例

# 映射视图的作用,使数据成为只读
from types import MappingProxyType
d = {1 : 'A'}
d_proxy = MappingProxyType(d)
d_proxy  #mappingproxy({1:'A'})
d_proxy[2] = 'x' #报错,不可修改该映射视图
d[2] = 'B'
d_proxy  #mappingproxy({1:'A', 2:'B' }) #修改原dict,对应的映射视图也会改变

19、

原文地址:https://www.cnblogs.com/hotsnow/p/10871460.html