补充
最近读了一本名叫Intermediate Python的书,对应的中文版是Python进阶,本文是读完之后的笔记。
列表
调试器
Python也有调试器,和gdb的指令基本一致。进入debug有两种方法,一种是运行程序的时候执行python -m pdb xxxx.py
;另一种是使用pdb
模块的set_trace()
方法在函数中间设置断点。
有没有用?求同存异吧。
可迭代对象、迭代器、迭代
Python中任意对象,只要实现了可以返回一个迭代器的__iter__
方法,或定义了可以支持下标索引的__getitem__
方法,那么它就是一个可迭代对象。
任何对象,只要定义了__next__
方法,它就是一个迭代器。
当我们是使用一个循环来遍历某个东西时,这个过程就是迭代。
Map, Filter, Reduce
通常和lambda表达式结合一起使用,但也可以是一个函数地址。格式均为:
Map/Filter/Reduce((lambda expression)|fn, items)
其中items必须是个可迭代的对象。
Map是将expression作用于items每个成员上,并返回一个新的可迭代对象。其lambda式或fn一般是一个参数。Map还可以这样写:
def multiply(x):
return (x*x)
def add(x):
return (x+x)
funcs = [multiply, add]
for i in range(5):
value = map(lambda x: x(i), funcs)
print (list(value))
Filter是过滤器,将符合lambda式或函数的值过滤出来形成新的返回对象。
Reduce是迭代处理一个迭代对象,因此其lambda式或函数一般带有两个参数,它首先作用于迭代对象的第一第二个元素,生成一个中间值,然后处理中间值和第三个元素,之后生成新的中间值,并和下一值结对处理,最后一般返回一个值。Python里Reduce被收到了functools模块里,需要像from functools import reduce
这样调用。
三元运算符
除了一般的:
is_fat = True
state = "fat" if is_fat else "not fat"
还可以这样写:
fat = True
fitness = ("skinny", "fat")[fat]
print("Ali is ", fitness)
但不推荐,有隐患:
condition = True
print(2 if condition else 1/0)
# 输出2
print((1/0, 2)[condition])
# 输出ZeroDivisionError异常
装饰器
补充两个关于装饰器的代码。
使用functools.wraps保存原函数的名字和注释文档
from functools import wraps
def a_new_decorator(a_func):
@wraps(a_func)
def wrapTheFunction():
print ("I am doing some boring work before executing a_func()")
a_func()
print ("I am doing some boring work after executing a_func()")
return wrapTheFunction
@a_new_decorator
def a_function_requiring_decoration():
"""Hey yo! Decorate me!"""
print("I am the function which needs some decoration to remove my foul smell")
print(a_function_requiring_decoration.__name__)
print(a_function_requiring_decoration.__doc__)
装饰器模板
from functools import wraps
def decorator_name(f):
@wraps(f)
def decorated(*args, **kwargs):
if not can_run:
return "Function will not run"
return f(*args, **kwargs)
return decorated
@decorator_name
def func():
return("Function is running")
can_run = True
print(func())
装饰器的使用场景
授权
from functools import wraps
def requires_auth(f):
@wraps(f)
def decorated(*args, **kwargs):
auth = request.authorization
if not auth or not check_auth(auth.username, auth.password):
authenticate()
return f(*args, **kwargs)
return decorated
日志
from functools import wraps
def logit(func):
@wraps(func)
def with_logging(*args, **kwargs):
print(func.__name__ + " was called")
return func(*args, **kwargs)
return with_logging
@logit
def addition_func(x):
"""Do some math."""
return x + x
result = addition_func(4)
__slots__
魔法
在Python中,每个类都有实例属性。默认情况下Python用⼀个字典来保存⼀个对象的实例属性。这非常有用,因为它允许我们在运⾏时去设置任意的新属性。
class MyClass(object):
__slots__ = ['name', 'identifier']
def __init__(self, name, identifier):
self.name = name
self.identifier = identifier
self.set_up()
这样写可以打打减少实例对象的内存使用,另外一款检测内存的模块ipython_memory_usage
虚拟环境
Virtualenv 是⼀个⼯具,它能够帮我们创建⼀个独⽴(隔离)的Python环境。
Collections模块
- defaultdict,高级字典,可以处理key重复的情况而不是抛出异常。
- counter,计数器,针对某项数据进行计数。
- deque,双端队列
- namedtuple,高级元组,可以生成一个带名字和字段的元组(但只是元组,这意味着值不能改变)
from collections import namedtuple
Animal = namedtuple('Animal', 'name age type') # 元组名称和参数(用空格分隔)
perry = Animal(name="perry", age=31, type="cat")
print(perry)
print(perry[0])
print(perry.name, perry.age, perry.type) # 进行类字典访问
print(perry._asdict()) # 转换为字典
- enum.Enum (Python 3.4+)
from enum import Enum
class Species(Enum):
cat = 1
dog = 2
horse = 3
aardvark = 4
butterfly = 5
owl = 6
platypus = 7
dragon = 8
unicorn = 9
print (Species(1))
print (Species['cat'])
print (Species.cat)
枚举 Enumerate
enumerate可以带参数,注意参数不是表示从第几个元素开始,是指从数字几开始枚举。
my_list = ['apple', 'banana', 'grapes', 'pear']
for c, value in enumerate(my_list, 2):
print(c, value)
# 输出,注意不是从第几个元素开始,是指从数字几开始枚举
# 4 apple
# 5 banana
# 6 grapes
# 7 pear
对象自省 Introspection
dir
返回一个列表,表示一个对象所拥有的全部属性和方法。如果我们运行dir()而传⼊参数,那么它会返回当前作⽤域的所有名字。
type和id
type函数返回一个对象的类型。id返回任意对象的唯一ID。
inspect模块
推导式(即之前所述的生成式)
列表推导式
它的结构是在⼀个中括号⾥包含⼀个表达式,然后是⼀个for语句,然后是0个或多个for或者if语句。
variable = [out_exp for out_exp in input_list if out_exp == 2]
字典推导式
mcase = {'a': 10, 'b': 34, 'A': 7, 'Z': 3}
mcase_frequency = {
k.lower(): mcase.get(k.lower(), 0) + mcase.get(k.upper(), 0)
for k in mcase.keys()
}
这个例子是把a
和A
的值合并到a
里面了。
集合推导式
{x**2 for x in [1, 1, 2]}
处理多个异常
try:
file = open('test.txt', 'rb')
except (IOError, EOFError) as e:
print("An error occurred. {}".format(e.args[-1]))
或者
try:
file = open('test.txt', 'rb')
except EOFError as e:
print("An EOF error occurred.")
raise e
except IOError as e:
print("An error occurred.")
raise e
或者用Exception
处理所有的异常。
lambda表达式
列表排序
a = [(1, 2), (4, 1), (9, 10), (13, -3)]
a.sort(key=lambda x: x[1])
列表并行排序
data = zip(list1, list2)
data.sort()
list1, list2 = map(lambda t: list(t), zip(*data))
for-else
for n in range(2, 10):
for x in range(2, n):
if n % x == 0:
print( n, 'equals', x, '*', n/x)
break
else:
# loop fell through without finding a factor
print(n, 'is a prime number')
Python2+3
Future模块导入
它可以帮你在Python2中导⼊Python3的功能。
模块重命名
try:
import urllib.request as urllib_request # for Python 3
except ImportError:
import urllib2 as urllib_request # for Python 2
urllib_request.XXXXXXX
失效Python2的内置功能
from future.builtins.disabled import *
apply()
协程
def grep(pattern):
print("Searching for", pattern)
while True:
line = (yield)
if pattern in line:
print(line)
search = grep('coroutine')
print (next(search))
print (search.send("Don't you love me?"))
print (search.send("I love coroutine instead!"))
search.close()
函数缓存
函数缓存允许我们将⼀个函数对于给定参数的返回值缓存起来。当⼀个I/O密集的函数被频繁使⽤相同的参数调⽤的时候,函数缓存可以节约时间。在Python 3.2版本以前我们只有写⼀个⾃定义的实现。在Python 3.2以后版本,有个lru_cache的装饰器,允许我们将⼀个函数的返回值快速地缓存或取消缓存。
from functools import lru_cache
@lru_cache(maxsize=32)
def fib(n):
if n < 2:
return n
return fib(n-1) + fib(n-2)
print([fib(n) for n in range(10)])