Python进阶学习
PS:感谢穆课网提供优秀的学习资源
高阶函数
- 定义: 能接收函数作为参数的函数,就是高阶函数;
示例:
def add(x,y,f): return f(x) + f(y) add(-5, 9, abs)
函数式编程
map(f, list) # 用f函数作用list的每一个元素,返回数组
reduce(f(x,y), list, z) # z:可选参数,作为计算的初始值,返回一个值
filter(f,list) # 返回被f函数过滤掉后的新list
sorted(list, f(x,y)) # 可以对list进行排序(f可选:如果x应该排在y的前面,返回-1,如果x应在排在y的后面,返回1;如果x和y相等,返回0)
返回函数
- Python的函数不但可以返回int、str、list、dict等数据类型,还可以返回函数
示例
# 编写一个函数calc_prod(lst),它接收一个list,返回一个函数,返回函数可以计算参数的乘积 def calc_prod(lst): def calc_prod2(): def f(x,y): return x * y return reduce(f,lst) return calc_prod2 f = calc_prod([1, 2, 3, 4]) print f() # 运行结果24
闭包
def count(): fs = [] for i in range(1, 4): def f(): return i*i fs.append(f) return fs f1, f2, f2 = count() print f1(),f2(),f3() # 运行f1(), f2(), f3() 结果都为9,所以返回函数不要引用任何环境变量,或者后续会发生变化的变量。 # 这个函数式我看了很久,运行了很多遍,从模糊不懂,到后来渐渐清晰,过程真是复杂崎岖,在自嘲自己理解能力差的同时,唯有感叹python博大精深!
解决上面问题的办法
def count(): fs = [] for i in range(1, 4): def f(j): def g(): return j * j return g fs.append(f(i)) return fs f1, f2, f3 = count() print f1(), f2(), f3() # 应用返回函数不适用任何后续会发生变化变量的原则
匿名函数
# 示例1 # 关键字lambda 表示匿名函数,冒号前面的 x 表示函数参数。 # 匿名函数有个显示,就是**只能有一个表达式,不写return**,返回值就是该表达式的结果; >>> map(lambda x: x * x, [1, 2, 3, 4, 5, 6, 7, 8, 9]) [1, 4, 9, 16, 25, 36, 49, 64, 81] # 示例2 >>> myabs = lambda x: -x if x < 0 else x
decorator装饰器
# 个人理解:定义一个函数B,接收一个函数A(x);函数B中定义一个函数C,函数C接收函数A的参数x,在函数C内部调用函数A(x),调用之前或折后可以打印一log或做一些特殊处理,函数C返回调用函数A(x)的结果(return A(x)),函数B返回函数C,这样调用函数C就可以获得函数A的结果,同时起到了装饰函数A的作用,最后再设置函数A = 函数B,就隐藏了原有的函数A,没有改变其代码却又装饰了函数。 # 示例:通过高阶函数返回函数对f1进行装饰,在fA执行前,打印一段日志 def fA(x): return x * 2 def fB(f): def fC(x): print 'call ' + f.__name__ + '()' return fA(x) return fB fA = fB(f) 也可以换种写法,就是在原函数fA(x)的头顶写上@new_fn
- 装饰器可以极大地简化代码,避免每个函数编写重复性代码
- 打印日志:@log
- 检测性能:@performance
- 数据库事物:@transaction
- URL路由:@post(‘/register’)
- 装饰器可以极大地简化代码,避免每个函数编写重复性代码
偏函数
functools.partial可以把一个参数多的函数变成一个参数少的新函数,少的参数需要在创建时指定默认值,这样,新函数调用的难度就降低了。
# 定义偏函数,简化比较函数代码 import functools sorted_ignore_case = functools.partial(sorted, cmp=lambda s1, s2 : cmp(s1.upper(), s2.upper())) print sorted_ignore_case(['bob', 'about', 'Zoo', 'Credit']) # 运行结果 ['about', 'bob', 'Credit', 'Zoo']
模块和包
导入import
导入模块
import math
导入方法
from math import pow
导入时使用别名
from math import pow as mypow
动态导入
try: import json except ImportError: import simplejson as json print json.dumps({'python':2.7})
导入第三方模块
- easy_install
pip(官方推荐)
# windows环境下(管理员身份打开命令提示符): pip install web.py
面向对象编程基础
定义类并创建对象
class Person(object): # 继承自object
passxiaoming = Person() xiaohong = Person()
创建实例属性
class Person(objcet): pass p1 = Person() p1.name = 'Bart' p2 = Person() p2.name = 'Adam' p3 = Person() p3.name = 'Lisa' L1 = [p1, p2, p3] l2 = sorted(L1, lambda x,y:cmp(x.name, y.name)) # 根据对象名字排序
初始化实例属性
class Person(object): # 构造函数 def __init__(self, name, gender, birth, **kw): self.name = name self.gender = gender self.birth = birth # 除了直接使用self.name = 'xxx'设置一个属性外,还可以通过setattr(self,'name','xxx')设置属性 for k,v in kw.iteritems(): setattr(self, k, v) #
访问限制
双下划线开头的属性无法被外部访问
class Person(object): def __init__(self, name, score): self.name = name self.__score = score p = Person('Bob', 59) print p.name print p.__score #会报错attributeerror
创建类属性
绑定在一个实例上的属性不会影响其他实例,但是,类本身也是一个对象,如果在类上绑定一个属性,则所有实例都可以访问类的属性,并且,所有实例访问的类属性都是同一个!也就是说,实例属性每个实例各自拥有,互相独立,而类属性有且只有一份。
# 计算类被创建了多少个对象 class Person(object): count = 0 def __init__(self, name): self.name = name Person.count += 1 p1 = Person('Bob') print Person.count p2 = Person('Alice') print Person.count p3 = Person('Tim') print Person.count
定义实例方法
class Person(object): # 隐藏score,只可以通过get_grade获得score的级别A,B,C def __init__(self, name, score): self.name = name self.__score = score def get_grade(self): grade = 'C' if self.__score >= 80: grade = 'A' elif self.__score >= 60: grade = 'B' return grade