参考资料 
格式化输出 
参考 
1 2 3 4 i = "my name is {name}" i = i.format(name="hg") print(i) #>>> my name is hg 
1 2 3 4 name = "hg" i = f"my name is {name}" print(i) #>>> my name is hg 
感觉还是f前缀好用
格式化字符串 
在数字或字符串后跟冒号,可以格式化字符串.
1 2 3 4 5 6 7 8 9 10 print(f"|{'qcdxhg':10}|") #>>> |qcdxhg    | # 冒号后跟数字,表示占用多大的位置.超过最大长度不作截取. print(f"|{'qcdxhg':10.4}|{'qcdxhg':10.8}|{10 + math.pi:10.5}|{10 + math.pi:.5}|") #>>> |qcdx      |qcdxhg    |    13.142|13.142| # 冒号后面数字的小数部分,表示字符串最大长度,截去超过长度的部分,如果被截取的是小数,同时还会四舍五入,并且小数点计入总长长度计算,不计入截取位数时的计算 # 数字向右对齐,字符串向左对齐 print(f"|{10 + math.pi:10.3f}|") #>>> |    13.142| # 内容是数字时,冒号后面的小数部分的后面跟个f,表示保留小数后几位(依然四舍五入) 
1 2 3 4 5 6 7 #除了用冒号以外,还可以用just函数来实现字符串占位长度(限字符串) print(f"|{'123'.ljust(10)}|{'123'.center(10)}|{'123'.rjust(10)}|") #>>> |123       |   123    |       123| # str.zfill(x)向数字字符串左侧填充0,到达长度为x.此时"-"和"."(负号和小数点)均计数 print(f"|{str(-123.54).zfill(10):15}|") #>>>|-000123.54     | 
数字文字 
可以添加下划线增加可读性
1 2 3 4 5 6 7 i = 1_000 print(i) #>>> 1000 print(str(i)) #>>> 1000 print(repr(i)) #>>> 1000 
重载运算符 
运算符 
运算 
正向方法 
反向方法 
就地方法 
 
 
+ 
取正 
__pos__ 
 
- 
取负 
__neg__ 
 
~ 
按位取反 
__invert__ 
 
 
== 
相等 
__eq__ 
 
!= 
不等 
__ne__ 
 
> 
大于 
__gt__ 
__lt__ 
 
< 
小于 
__lt__ 
__gt__ 
 
>= 
大于等于 
__ge__ 
__le__ 
 
<= 
小于等于 
__le__ 
__ge__ 
 
 
+ 
加法 
__add__ 
__radd__ 
__iadd__ 
 
- 
减法 
__sub__ 
__rsub__ 
__isub__ 
 
* 
乘法 
__mul__ 
__rmul__ 
__imul__ 
 
/ 
除法 
__truediv__ 
__rtruediv__ 
__itruediv__ 
 
// 
整除 
__floordiv__ 
__rfloordiv__ 
__ifloordiv__ 
 
% 
取余 
__mod__ 
__rmod__ 
__imod__ 
 
divmod() 
整除并取余 
__divmod__ 
__rdivmod__ 
__idivmod__ 
 
**, pow() 
取幂 
__pow__ 
__rpow__ 
__ipow__ 
 
@ 
矩阵乘法 
__matmul__ 
__rmatmul__ 
__imatmul__ 
 
& 
按位与 
__and__ 
__rand__ 
__iand__ 
 
| 
按位或 
__or__ 
__ror__ 
__ior__ 
 
^ 
按位异或 
__xor__ 
__rxor__ 
__ixor__ 
 
<< 
按位左移 
__lshift__ 
__rlshift__ 
__ilshift__ 
 
>> 
按位右移 
__rshift__ 
__rrshift__ 
__irshift__ 
 
 
不支持计算时,函数返回NotImplement.
切片 
流畅的python p234解释了原理
1 2 3 4 5 6 7 a = "abcdefgh" print(a[::2]) #>>> aceg print(a[::-1]) #>>> hgfedcba # 通过[::-1]可实现倒序排列 # effective python建议不要指定了start或end的同时指定stride,因为难以理解. (可以分开写) 
切片放在赋值语句的左边或者作为del操作的对象,可以轻松地操作序列
1 2 3 4 5 6 7 8 9 10 11 12 13 l = list(range(10)) l[2:5] = [20, 30] print(l) #>>> [0, 1, 20, 30, 5, 6, 7, 8, 9] del l[5:7] print(l) #>>> [0, 1, 20, 30, 5, 8, 9] l[::2] = [22, 33, 44, 55] print(l) #>>> [22, 1, 33, 30, 44, 8, 55] l[2:5] = [100] print(l) #>>> [22, 1, 100, 8, 55] 
encode和decode 
str.encode()可以用于使用给定的文本编码将str转换为bytes,
元组 
元组与list类似,不同之处:
元组的元素不能修改 
元组可以作为map的键,list不可以 
元组的拆包 
 
1 2 3 4 5 6 7 8 9 # 一个元组只有一个元素时,一定要在这个元素后加逗号 tup1=("sqh",) tup2=("sqh","123") print(tup1) #>>> ('sqh',) print(tup2) #>>> ('sqh', '123') print(tup2[0]) #>>> sqh 
1 2 3 4 5 t = ("ddd","sss") m = {t:"aaa"} print(m[t]) #>>> aaa #元组作为map的键 
1 2 3 4 5 6 7 8 9 a, b, c = (1, 2, 3) print(a, b, c) #>>> 1 2 3 #元组的平行赋值就是拆包 x, y, *rest = range(5) print(x, y, rest) #>>> 0 1 [2, 3, 4] #用*处理剩下的元素 
具名元组 
collections.namedtuple构建的类的实例所消耗的内存跟元组是一样的,因为字段名都存在对应的类里面.这个实例跟普通的对象实例比起来也要小一些,因为python不会用__dict__来存放这些实例的属性.
1 2 3 4 5 6 7 8 from collections import namedtuple T = namedtuple("ANAMEDTUPLE","a b c d") t = T("A","B","C","D") print(t) #>>> ANAMEDTUPLE(a='A', b='B', c='C', d='D') print(f"t.a = {t.a}") #>>> t.a = A 
字典的默认值 
dict.get(k,default) 
dict.setdefault(self,key,value) 
1 2 3 4 5 6 7 8 9 10 11 12 d = {     "a": 0 } print(d.get("b", 255)) #>>> 255 #dict.get(key,default)实现默认值 d.setdefault("b", 233) print(d["b"]) #>>> 233 #dict.setdefault(self,key,value)实现默认值 
collections.defaultdict(type) 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import collections d2 = collections.defaultdict(list) print(d2) #>>> defaultdict(<class 'list'>, {}) print(d2["a"]) #>>> [] #出现了,默认值是空list d2["b"].append(666) #d2["b"]的默认值是[],所以可以直接append print(d2) #>>> defaultdict(<class 'list'>, {'a': [], 'b': [666]}) #访问过的d2["a"]也有值了 d2["c"] = 3 print(d2) #>>> defaultdict(<class 'list'>, {'a': [], 'b': [666], 'c': 3}) #defaultdict并没有限制数据类型 
1 2 3 4 5 6 7 8 9 10 11 12 13 d3 = collections.defaultdict(tuple) print(d3["a"]) #>>> () d4 = collections.defaultdict(int) print(d4["a"]) #>>> 0 d5 = collections.defaultdict(bool) print(d5["a"]) #>>> False #各个数据类型的默认值貌似是bool值为False的值 
missing 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 class strDict(dict):     def __init__(self,*args,**kwargs):         super(strDict, self).__init__(*args,**kwargs)     def __missing__(self, key):         if isinstance(key,str):             raise KeyError(key)             #如果找不到的键本来就是str,则报错         else:             return self[str(key)]             #如果找不到的键不是str,则找str化的键     def __contains__(self, key):         return key in self.keys() or str(key) in self.keys()         #先按照原本的值查找,找不到再str之后再找 a = strDict() a["123"] = 233 #存值的时候,键是字符串 print(a[123]) #>>> 233 #取值的时候用int也能取出. 
__getattr__,__getattribute__,__setattr__控制对象属性 
effective python 第97页
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 class O:     def __init__(self):         self.a = 1         self.b = 2     def __getattr__(self, item):         print(f"""not has attr named '{item}'""")     def __getattribute__(self, item):         print(f"""try to accept to '{item}'""")         return super().__getattribute__(item) o = O() o.__setattr__("c",3) #>>> try to accept to '__setattr__' setattr(o,"d",4) print(o.__dict__) #>>> try to accept to '__dict__' #>>> {'a': 1, 'b': 2, 'c': 3, 'd': 4} o.e #>>> try to accept to 'e' #>>> not has attr named 'e' 
排序 
sorted(iterable,key,reverse)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 class S:     def __init__(self, v: int):         self.v = v l = [     S(8),     S(6),     S(1),     S(2) ] for s in l:     print(s.__dict__) #>>> {'v': 8} #    {'v': 6} #    {'v': 1} #    {'v': 2} l = sorted(l, key=lambda x: x.v) for s in l:     print(s.__dict__) #>>> {'v': 1} #    {'v': 2} #    {'v': 6} #    {'v': 8} 
list.sort()是就地修改
bisect 
bisect.bisect 返回一个数插入有序列表的位置,不会将这个数插入数组
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import bisect x = list(range(20)) x = x[::3] print(x) #>>> [0, 3, 6, 9, 12, 15, 18] i0 = bisect.bisect(x, 2) print(i0) #>>> 1 #返回应该插入的位置 print(x) #>>> [0, 3, 6, 9, 12, 15, 18] #原列表未被修改 i1 = bisect.insort(x, 2) print(i1) #>>> None #返回None print(x) #>>> [0, 2, 3, 6, 9, 12, 15, 18] #原列表已被修改 
array 
流畅的python P41
浅拷贝与深拷贝 
流畅的python p187
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 import copy l0 = [233,255] l1 = [0,1,2,l0,5] #引用了l0 l2 = l1 #引用赋值 l3 = list(l1) #构造函数实现浅拷贝 l4 = l1[:] #list的解构(?)实现浅拷贝 l5 = copy.copy(l1) #copy模块浅拷贝 l6 = copy.deepcopy(l1) #copy模块深拷贝 print(l2 is l1) #>>> True print(l3 is l1) #>>> False print(l4 is l1) #>>> False print(l5 is l1) #>>> False print(l6 is l1) #>>> False l0.append(798) print(l2) #>>> [0, 1, 2, [233, 255, 798], 5] print(l3) #>>> [0, 1, 2, [233, 255, 798], 5] print(l4) #>>> [0, 1, 2, [233, 255, 798], 5] print(l5) #>>> [0, 1, 2, [233, 255, 798], 5] #因为是浅拷贝,拷贝了l1中对l0的引用,所以l0更改了,l3,l4,l5也会更改 print(l6) #>>> [0, 1, 2, [233, 255], 5] #l6是深拷贝,没有拷贝l1对l0的引用,而是新创建了一份和l0一样的列表,因此没有改变 
在pythontutor 执行可以清晰地看懂原理
del和垃圾回收 
python手册,data model一章中的一句话:对象绝不会自行销毁;然而,无法得到对象时,可能会被当做垃圾回收.
弱引用 
流畅的python p196
1 2 class myList(list):     pass 
yield 
yield是协程的体现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 def fab(max):     n, a, b = 0, 0, 1     while n < max:         yield b         a, b = b, a + b         n = n + 1 f = fab(5) print(f) #>>> <generator object fab at 0x056AF0F0> print(type(f)) #>>> <class 'generator'> for n in f:     print(n,end="|") #>>> 1|1|2|3|5| ```   私自理解为,yield可以使一个函数先后返回几个不同的值 
import requests
def findBiliAidInURL(url: str):
# 在第二个yield前,通过网络IO请求视频某些信息,然后yield出去
api = f"https://api.bilibili.com/x/web-interface/archive/stat"
url_ = f"https://www.bilibili.com/video/av{aid}"
headers = {
    "refer": url_,
    "Origin": "https://www.bilibili.com",
    "Host": "api.bilibili.com",
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36",
}
res = requests.get(api, params={"aid": aid}, headers=headers)
res.encoding = "utf8"
yield res.text
if name  == ‘main ’:https://www.bilibili.com/video/av42684155 ”)
1 2 3 4 ## is 和 ==   is比较二者内存地址,\=\=比较二者值.与js的\=\=和\=\=\=不同,js的\=\=和\=\=\=的差异在于是否比较等号两边的数据类型.id(x)获取x内存位置   用is判断None: 
x = None
True
 
 
 
import math
a = (“a”,“b”,“c”)
c = [(x,y) for x in a
class A:init (self, a: int):
ls = []
ds = {a.x: a.dict  for a in ls}
1 2 3 4 ## 生成器表达式   列表推导有个缺点:在推导过程中,对于输入序列中的每个值来说,都要创建一个仅含一项元素的全新列表,当输入数据比较大时容易占内存较大.   生成器表达式则不会有这种问题.   生成器表达式生成一个\<class'generator'\>,通过next(generator)取值.相对列表推导式的优点在于可以按需取用,避免过大占用内存 
列表推导式 
a = [x for x in range(100)]
生成器表达式 
b = (x for x in range(100))
a = sum(x for x in range(101))
1 2 ## 可迭代对象 可迭代对象要实现\_\_iter\_\_函数.如果实现了\_\_next\_\_函数,则\_\_iter\_\_函数可return self;否则要return一个iterable,如列表,生成器等   
class R:init (self):
def __iter__(self):
    return self
    #只要实现了__iter__函数,实例自身就是一个iterable.被遍历的时候会调用__next__函数
def __next__(self):
    if self.x > 5:
        raise StopIteration
    self.x += 1
    return self.x
for i in R():
2 
3 
4 
5 
6 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ``` class I:     def __init__(self):         pass     def __iter__(self):         return (int(random.random() * 100) for i in range(5))         #返回生成器 for i in I():     print(i) #>>> 33 #    50 #    97 #    65 #    60 
对象的格式化输出
1 2 3 4 5 6 7 8 9 10 11 12 class People:     def __init__(self,name:str,age:int):         self.name = name         self.age = age     def __format__(self, format_spec):         return format_spec.replace("%n",self.name).replace("%a",str(self.age)) p = People("ababa",15) f = format(p,"%n ages %a") print(f) #>>> ababa ages 15 
对象的__slots__ 
定义了__slots__属性的目的是告诉解释器:“这个类中的所有实例属性都在这儿了”,这样,python会在各个实例中使用类似元组的数据结构存储实例变量,从而避免使用消耗内存的__dict__
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 class A:     __slots__ = ("__x")     #__slots__是一个iterable,用元组好点     #只需声明实例变量名即可,不用声明方法名.     def __init__(self, a: int):         self.__x = a     def addA(self):         self.__x += 1     @property     #通过property声明的属性不用写在__slots__里     def x(self):         return self.__x     @x.setter     def x(self, x):         self.__x = x     @x.getter     def x(self):         return self.__x a = A(5) print(a.x) #>>> 5 a.x = 6 print(a.x) #>>> 6 a.addA() print(a.x) #>>> 7 print(vars(a)) #>>> TypeError: vars() argument must have __dict__ attribute #不能使用vars()或者__dict__获得其属性了. 
有需求的话,也可以在__slots__里写上"dict ",实例也会在__dict__里存储属性.不过这样做就达不到
装饰器 
装饰器能在被装饰的函数执行之前和之后分别执行一些代码,可以做到访问及修改原函数的参数和返回值,以实现约束语义,调试函数,注册函数等目标
1 2 3 4 5 6 7 8 9 10 11 12 def aDecorator(aFn):     def aWapper():         return "-------" + aFn() + "----------"     return aWapper @aDecorator def a():     return "aaa" s = a() print(s) #>>> -------aaa---------- 
参数化装饰器 
参数化的装饰器其实不是装饰器,而是装饰器的工厂函数,返回一个装饰器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 #装饰器函数工厂函数,接受参数 def aDecorateFactory(anArg="nothing"):          #装饰器函数,接受被装饰的函数做参数     def decorate(func):                  #装饰后的函数,接受任意参数以传给被装饰的函数         def retfunc(*args):                          #执行装饰器附加代码             print(anArg,end="")                          res = func(*args)             #执行被装饰的函数,装饰后的函数返回其执行结果             return res                  return retfunc         #装饰器函数返回装饰后的函数              return decorate     #工厂函数返回装饰器      @aDecorateFactory("something") def printsth(sth):     print(sth) printsth("666") #>>> something666 
装饰器的问题 
修饰器返回了一个新的函数,并非原函数.两者在使用之外的地方可能会有不同.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 def addA(s:str)->str:     return s + "aaaaaaa" print(addA) #>>> <function addA at 0x048ACFA8> print(addA.__name__) #>>> addA def aDecorator(func):     def aWapper(*args,**kwargs):         res = func(*args,**kwargs)         print(res)         return res     return aWapper @aDecorator def addA2(s:str)->str:     return s + "aaaaaaa" print(addA2) #>>> <function aDecorator.<locals>.aWapper at 0x048D3030> print(addA2.__name__) #>>> aWapper 
这个问题可以用functools模块的@functools.wraps()修饰器解决.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 import functools def aDecorator2(func):     @functools.wraps(func)     #重点在这行     def aWapper(*args,**kwargs):         res = func(*args,**kwargs)         print(res)         return res     return aWapper @aDecorator2 def addA3(s:str)->str:     return s + "aaaaaaa" print(addA3) #>>> <function addA3 at 0x045B2108> print(addA3.__name__) #>>> addA3 
标准库中的装饰器: 
@property 
廖雪峰教程  | effective python 第84页
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 class Candies:     def __init__(self):         self._peoples = 1         self._candies = 10         self._candiesPerple = 10     @property     def peoples(self):         return self._peoples     @peoples.setter     def peoples(self,peoples):         self._peoples = peoples         self._candiesPerple = self._candies // self._peoples         print("设置peoples")     @peoples.getter     def peoples(self):         print("读取peoples")         return self._peoples c = Candies() c.peoples = 5 #>>> 设置peoples p = c.peoples #>>> 读取peoples print(p) #>>> 5 
@staticmethod和@classmethod 
Python类中有3个方法,即静态方法(staticmethod),类方法(classmethod)和实例方法.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 def fn(x):     print(f"executing fn({x})") class A(object):     # 实例方法,参数带有self     def fn(self,x):         print(f"executing fn({self},{x})")     # 类方法,参数带有cls,感觉是拿来更改类变量的     @classmethod     def class_fn(cls,x):         print(f"executing class_fn({cls},{x})")          # 静态方法     @staticmethod     def static_foo(x):         print(f"executing static_foo({x})") a=A() a.fn(3) #>>> executing fn(<__main__.A object at 0x057A7AD0>,3) a.class_fn(4) #>>> executing class_fn(<class '__main__.A'>,4) a.static_foo(5) #>>> executing static_foo(5) A.fn(6) # 报错 A.fn(7,8) #>>> executing fn(7,8) # 实际是把7传给self,self作为一个普通的参数 A.class_fn(9) #>>> executing class_fn(<class '__main__.A'>,9) A.static_foo(10) #>>> executing static_foo(10) 
类方法可以拿来做备选的构造方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 class A:     def __init__(self,a):         self.x = a     @classmethod     def from10(cls):         return cls(10) a = A(5) print(a.__dict__) #>>> {'x': 5} b = A.from10() print(b.__dict__) #>>> {'x': 10} 
见functools.lru_cache 
见装饰器的问题 
函数注释 
python文档 
1 2 3 4 def f(a : str, b : "b is a string", c : int = 5) -> str:     return str(a) + str(b) + str(c) print(f(123,"sss")) #>>> 123sss5 
时间计算 
参考 
python包发布 
python包发布 官方文档 
pickle 
python文档 
较实用的python内置方法 
divmod(num,num) 
把除法和求余结合起来,返回a // b, a % b
enumerate(list) 
遍历列表,同时列出下标
all(iterable) 
一个iterable全部元素为True,则返回True,否则返回False
any(iterable) 
一个iterable全部元素为False,则返回False,否则返回True
repr(object) 
将对象转化为供解释器读取的形式。程序 理解的字符串,str将对象转化为供人类 理解的字符串
1 2 3 4 5 6 i = "my name is sqh\ni age 20" print(str(i)) #>>> my name is sqh i age 20 print(repr(i)) #>>> 'my name is sqh\ni age 20' 
1 2 3 4 5 6 7 8 9 10 11 # 对于dict和list i = {"name":"sqh","age":20} print(i) #>>> {'name': 'sqh', 'age': 20} print(str(i)) #>>> {'name': 'sqh', 'age': 20} print(repr(i)) #>>> {'name': 'sqh', 'age': 20} print(repr(i)[0]) #>>> { # repr后转换为字符串,打印字符串的0位置的字符 
map(function,iterable) 
map() 会根据提供的函数对指定序列做映射
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 a = [     {"id": 0, "name": "foo"},     {"id": 1, "name": "bar"} ] b = map(lambda x: x["name"], a) print(b) # 返回迭代器 #>>> <map object at 0x02D3E150> print(list(b)) #>>> ['foo', 'bar'] import math c = [2,3,4] d = map(math.sqrt,c) print(d) #>>> <map object at 0x00336B50> print(list(d)) #>>> [1.4142135623730951, 1.7320508075688772, 2.0] print("\n".join(map(lambda a:" | ".join(map(lambda b:f"{a} * {b} = {a * b}",range(1,a + 1))),range(1,10)))) #一行输出九九乘法表 
tuple(iterable) 
tuple() 函数将列表(?)转换为元组
1 2 3 4 5 6 7 8 9 10 11 12 l = ["a", "b", "c"] print(tuple(l)) #>>> ('a', 'b', 'c') d = {     "k1": "v1",     "k2": "v2",     "k3": "v3" } print(tuple(d)) #>>> ('k1', 'k2', 'k3') #dict 返回dict的键 
filter(function,list) 
筛选list的元素
1 2 3 4 5 6 import math l = filter(lambda x:not math.sqrt(x) % 1, range(1, 101)) print(l) #>>> <filter object at 0x01B66B50> print(list(l)) #>>> [1, 4, 9, 16, 25, 36, 49, 64, 81, 100] 
vars(object) 
vars函数返回对象object的属性和属性值的字典对象。实现方式好像是 return obj.__dict__?(所以还是直接obj.__dict__吧…)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 class A:     x = 1     def __init__(self):         self.y = 2              def __getattribute__(self, item):         print(f"""try to accept to '{item}'""")         return super().__getattribute__(item) a = A() print(vars(a)) #>>> try to accept to '__dict__' #>>> {'y': 2} #只返回object的属性 
reversed(list) 
倒序列表
1 2 3 4 5 6 7 8 9 10 11 12 a = ["a", "s", "d", "f", "g"] print(list(reversed(a))) #>>> ['g', 'f', 'd', 's', 'a'] #reversed返回一个迭代器 a.reverse() print(a) #>>> ['g', 'f', 'd', 's', 'a'] # a.reverse()直接将a倒序,而不是a = a.reverse() #但是感觉没必要啊...切片就好了 print(a[::-1]) 
zip() 
这玩意不知怎么描述
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 a = "qwertyui" b = "asdfghjk" c = "zxcvbnm," print(list(zip(a,b,c))) #>>> [('q', 'a', 'z'), ('w', 's', 'x'), ('e', 'd', 'c'), ('r', 'f', 'v'), ('t', 'g', 'b'), ('y', 'h', 'n'), ('u', 'j', 'm'), ('i', 'k', ',')] #就是组成一个个元组 d = [     [100,200,300],     [40,50,60],     [7,8,9,1,1,1,1,1,1,1,1,1] ] print(list(zip(*d))) #>>> [(100, 40, 7), (200, 50, 8), (300, 60, 9)] #将每三个数组成一个元组,可以后续传递给函数 
set(iterable) 
set()函数创建一个无序不重复元素集,可进行关系测试,删除重复数据,还可以计算交集,差集,并集等
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 a = [1,1,2,3,4,5,1,6] print(a) print(set(a)) #>>> {1, 2, 3, 4, 5, 6} #可以去重 b = [4,5,6,9,8,7,18,29,38] # print(a|b) #>>> TypeError: unsupported operand type(s) for |: 'list' and 'list' print(set(a)|set(b)) #>>> {1, 2, 3, 4, 5, 6, 7, 8, 9, 38, 18, 29} c = "qwe" d = "asd" # print(c|d) #>>> TypeError: unsupported operand type(s) for |: 'str' and 'str' print(set(c)|set(d)) #>>> {'a', 's', 'd', 'w', 'e', 'q'} 
slice 
创建一个切片对象,经常用到的切片参数可以用slice存给一个变量
1 2 3 4 s = slice(None, None, -1) a = "qwer" print(a[s]) #>>> rewq 
reduce(function,iterable,initial) 
function接受两个参数,reduce首先把iterable的前两个元素传给函数参数,函数加工后,再把返回值和第三个元素作为两个参数传给函数参数,以此类推
1 2 3 4 5 6 7 8 9 10 from functools import reduce l =  [1, 2, 3, 4, 5, 6, 7, 8, 9] a = reduce(lambda x,y:x*10 + y,l) print(a) #>>> 123456789 b = reduce(lambda x,y:x*10 + y,l,7) print(b) #>>> 7123456789 #如果传入了initial参数,则第一次调用function的时候,是先将initial和iterable第一个元素作为参数 
partial 
将函数的第一个参数冻结住
1 2 3 r = functools.partial(range,10) print(list(r(20))) >>> [10, 11, 12, 13, 14, 15, 16, 17, 18, 19] 
operator 
operator模块为多个算术运算符提供了对应的函数,从而避免lambda a, b: a * b这种平凡的匿名函数.
1 2 3 4 5 6 import operator import functools def fact(n):     return functools.reduce(operator.mul, range(1, n + 1))     return functools.reduce(lambda a, b: a * b, range(1, n + 1))     #两行效果一样 
操作 
表达式 
函数 
 
 
加法 
a + b 
add(a, b) 
 
减法 
a - b 
sub(a, b) 
 
乘法 
a * b 
mul(a, b) 
 
除法 
a / b 
div(a, b) 
 
整除 
a // b 
floordiv(a, b) 
 
取余 
a % b 
mod(a, b) 
 
乘方 
a ** b 
pow(a, b) 
 
正运算 
+ a 
pos(a) 
 
负运算 
- a 
neg(a) 
 
取绝对值运算 
abs(a) 
abs(a) 
 
按位与 
a & b 
and_(a, b) 
 
按位或 
a | b 
or_(a, b) 
 
按位异或 
a ^ b 
xor(a, b) 
 
按位取反 
~a 
invert(a) 
 
左移位 
a << b 
lshift(a, b) 
 
右移位 
a >> b 
rshift(a, b) 
 
小于比较 
a < b 
lt(a, b) 
 
小于等于比较 
a <= b 
le(a, b) 
 
等于比较 
a == b 
eq(a, b) 
 
不等于比较 
a != b 
ne(a, b) 
 
大于等于比较 
a >= b 
ge(a, b) 
 
大于比较 
a > b 
gt(a, b) 
 
 
算了,不总结了,随用随查…
itemgetter() 
序列,dict元素的获取
1 2 3 4 5 6 7 8 a = ["a","b","c"] b = [2,5,7,4,8,9,6] g = operator.itemgetter(1) print(g(a)) #>>> b print(g(b)) #>>> 5 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ls = [     [8, 5, 4, 7],     [0, 1, 2, 3],     [6, 3, 1, 5, 4],     [2, 8, 7, 4] ] print(ls) #>>> [[8, 5, 4, 7], [0, 1, 2, 3], [6, 3, 1, 5, 4], [2, 8, 7, 4]] ls.sort(key=operator.itemgetter(0)) ls.sort(key=lambda l: l[0]) # 效果一样 print(ls) #>>> [[0, 1, 2, 3], [2, 8, 7, 4], [6, 3, 1, 5, 4], [8, 5, 4, 7]] 
1 2 3 4 5 6 7 8 9 ls2 = [     {"q":5},     {"q":8},     {"q":4},     {"q":7} ] ls2.sort(key=operator.itemgetter("q")) print(ls2) #>>> [{'q': 4}, {'q': 5}, {'q': 7}, {'q': 8}] 
attrgetter() 
对象属性的获取
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 class A:     def __init__(self):         self.x = int(random.random() * 100) ls = [A() for i in range(3)] for l in ls:     print(l.__dict__,end="") #>>> {'x': 95}{'x': 89}{'x': 89} ls.sort(key=operator.attrgetter("x")) ls.sort(key=lambda a:a.x) #效果一样 print("\n",end="") for l in ls:     print(l.__dict__,end="") #>>> {'x': 89}{'x': 89}{'x': 95} 
lru_cache 
据说是非常实用的装饰器,实现了备忘功能.这是一项优化技术,把耗时的函数的结果保存起来,避免传入相同的参数时重复计算.lru是"latest recently used"的缩写,表明缓存不会无限制增长,一段时间内不用的缓存条目会被扔掉.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 def fibonacci(n):     t = time.perf_counter()     if n < 2:         res = n     else:         res = fibonacci(n - 2) + fibonacci(n - 1)     t1 = time.perf_counter() - t     print(f"function fibonacci({n}) has excuted in {t1}s")     return res fibonacci(4) #>>> function fibonacci(0) has excuted in 3.950615723213543e-07s #    function fibonacci(1) has excuted in 0.0s #    function fibonacci(2) has excuted in 3.950615723213542e-05s #    function fibonacci(1) has excuted in 0.0s #    function fibonacci(0) has excuted in 3.950615723213573e-07s #    function fibonacci(1) has excuted in 3.950615723213505e-07s #    function fibonacci(2) has excuted in 1.540740132053282e-05s #    function fibonacci(3) has excuted in 2.8444433207137508e-05s #    function fibonacci(4) has excuted in 8.414811490444843e-05s #拿functools.lru_cache修饰后,函数调用次数减少 @functools.lru_cache() def fibonacci(n):     t = time.perf_counter()     if n < 2:         res = n     else:         res = fibonacci(n - 2) + fibonacci(n - 1)     t1 = time.perf_counter() - t     print(f"function fibonacci({n}) has excuted in {t1}s")     return res fibonacci(4) #>>> function fibonacci(0) has excuted in 0.0s #    function fibonacci(1) has excuted in 3.950615723213505e-07s #    function fibonacci(2) has excuted in 5.9259235848203126e-05s #    function fibonacci(3) has excuted in 1.5802462892854156e-06s #    function fibonacci(4) has excuted in 9.362959264016094e-05s 
使用lru_cache()时要加括号,因为其可以接受两个可选参数.
1 functools.lru_cache(maxsize=128,typed=false) 
maxsize参数置顶存储多少个调用结果.为了得到最佳性能,maxsize应该设为2的幂.typed设为True,则把不同类型的参数得到的结果分开保存
singledispatch 
单分派反函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 @functools.singledispatch def str2list(obj):     pass @str2list.register(str) #各个专门函数用@{base_function}.register({type})装饰. def _(aStr):     #函数名无所谓,"_"占位是个不错的选择     return list(aStr) @str2list.register(int) def _(anInteger):     return list(str(anInteger)) @str2list.register(tuple) @str2list.register(list) #指定多个类型 def _(anIterable):     return anIterable      print(str2list(123)) #>>> ['1', '2', '3'] print(str2list("abc")) #>>> ['a', 'b', 'c'] print(str2list([",",".","/"])) #>>> [',', '.', '/'] 
collections 
流畅的python p65,暂不研究
上下文管理器 
可以理解为,上下文管理器是一个特殊的类,包含__enter__和__exit__两个特殊方法.进入with里的语句时,执行上下文管理器的__enter__方法,离开时执行__exit__方法.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 from datetime import datetime class timePrint:     def __enter__(self):         global print         self.rawPrint = print         print = self.timePrint     def timePrint(self,*args,**kwargs):         timeStr = datetime.now().strftime("[%Y-%m-%d %H:%M:%S]")         self.rawPrint(timeStr,*args,**kwargs)     def __exit__(self, exc_type, exc_val, exc_tb):         global print         print = self.rawPrint if __name__ == '__main__':     with timePrint():         # 进入上下文管理器timePrint时执行__enter__(),print函数会被替换         print(1)         >>> [2019-02-08 02:18:07] 1     # 离开时,执行__exit__(),print函数会换回来     print(2)     >>> 2 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 # 这里是一个简陋的类似python自带的open上下文管理器的myopen上下文管理器.   # 与上面的例子区别在于,这个上下文管理器在构建时有传入参数,且__enter__函数有返回值 class myOpen():     # 构建上下文管理器时,传入的参数还是传给__init__函数而非__enter__函数     def __init__(self, filePath):         self.filePath = filePath     def __enter__(self):         self.__F = open(self.filePath, "r", encoding="utf8")         return self.__F     def __exit__(self, exc_type, exc_val, exc_tb):         self.__F.close() if __name__ == '__main__':     # 会将上下文管理器的__enter__的返回值传给as后面的变量     with myOpen("0.txt") as f:         print(f.read())         # >>> here's content of 0.txt 
@contexmanager修饰器 
@contexmanager修饰器能减少创建上下文管理器需要的样板代码量.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 from contextlib import contextmanager # contextmanager在contextlib中 @contextmanager def myOpen2(filePath):     # 定义一个函数而非一个类     # 构建上下文管理器时需要传给上下文管理器的参数直接传给本函数          __F = open(filePath, "r", encoding="utf8")     # yield前做__enter__函数需要做的事     # yield的值为__enter__函数返回的值     yield __F     # yield后做__exit__函数需要做的事     __F.close() if __name__ == '__main__':     with myOpen2("0.txt") as f:         print(f.read())         # >>> here's content of 0.txt         # 与上面的例子一致