Python进阶
2015.8.5
慕课网Python进阶学习:
函数式编程(functional):
1.python不是纯函数式编程:允许存在变量
2.支持高阶函数:函数可作为变量传入
3.支持闭包:有了闭包就能返回函数
4.有限度的支持匿名函数
高阶函数:能接收函数作为参数的函数。
def add(x,y,f):return f(x)+f(y)print add(4,5,abs)
其中abs是个求值函数
map()函数:它接收一个函数f和一个list,通过函数f依次作用在list的每个元素上
def format_name(s):a=s[:1].upper()+s[1:].lower()return aprint map(format_name,['adam','LISA','barT'])
reduce()函数:它接收一个函数f和一个list,它传入的函数f必须接收两个参数,对list反复调用f并返回最总结果值。也可接收第三个参数为它的初始值。
def prod(x, y):return x*yprint reduce(prod,[2,4,5,7,12])print reduce(prod,[2,4,5,7,12],100)
第一个输出的运算形式:prod(2,4)=8 ;=>prod(8,5)=40;=>.......依次相乘
第二个输出的运算形式:prod(100,2)=200 ;=>prod(200,4)=800;=>.......依次相乘
filter()函数:它接收一个函数f和一个list,f对每个元素进行判断,返回true或false,filter()通过判断结果自动过滤不符合条件的元素,返回由符合条件元素组成的新的list
import mathdef is_sqr(x):r=int(math.sqrt(x))return r*r==xprint filter(is_sqr, range(1,100))
math.sqrt(x)求x的平方根,返回结果是浮点数,int()将其转为int类型
sorted()自定义排序函数:接收一个比较函数f和一个list,f接收两个待比较的元素x,y,如果x应该排在y的前面,返回-1,如果x应该排在y的后面返回1,如果x,y相等,返回0
def cmp_ignore_case(s1, s2):u1=s1.upper()u2=s2.upper()if u1<u2:return-1if u1==u2:return0if u1>u2:return1print sorted(['bob','about','Zoo','Credit'],cmp_ignore_case)
从小到大排列,忽略大小写
返回函数:
def calc_prod(lst):def g():def d(x,y):return x * yreturn reduce(d,lst,1)return gf = calc_prod([1,2,3,4])print f()
闭包:内层函数应用了外层函数的变量,然后返回内层函数的情况称为闭包。注意:返回函数不要引用任何循环变量或者后续会发生编发的变量
def count():fs =[]for i in range(1,4):def f(x):def g():return x*x;return gr=f(i)fs.append(r)return fsf1, f2, f3 = count()print f1(), f2(), f3()
匿名函数:lambda 只能有一个表达式,不写return,返回值就是该表达式的结果
print filter(lambda s:s and len(s.strip())>0,['test',None,'','str',' ','END'])
s为匿名函数参数
2015.8.6
装饰器(decorator):
极大的简化代码,避免每个函数编写重复性代码
使用@在调用装饰器函数的函数之前
不带参数装饰器
打印日志:@log
def log(f):def fn(x):print'call '+ f.__name__ +'()...'return f(x)return fn@logdef factorial(n):return reduce(lambda x,y: x*y, range(1, n+1))print factorial(10)#此处代码如下
factorial=log(对于参数不是一个的,调用将报错,@log写死了只含有一个参数的返回值,要让@log自适应任何参数的函数可以使用*args和**kw,保证任意个参数都能正常调用
def log(f):def fn(*args,**kw):print'call '+ f.__name__ +'()...'return f(*args,**kw)return fn@logdef factorial(n):return reduce(lambda x,y: x*y, range(1, n+1))print factorial(10)检测性能:@performance
import time def performance(f):def fn(*args,**kw): t1=time.time() r=f(*args,**kw) t2=time.time()print'call %s() in %fs'%(f.__name__,(t2-t1))return rreturn fn@performancedef factorial(n):return reduce(lambda x,y: x*y, range(1, n+1)) print factorial(10)数据库事务:@transaction
URL路由:@post('/register')
带参数的装饰器
def log(str):def log_decorator(f):def fn(*args,**kw):print'call [%s] %s()...'%(str,f.__name__)return f(*args,**kw)return fnreturn log_decorator@log('debug')def factorial(n):return reduce(lambda x,y: x*y, range(1, n+1))#factorial=log(factorial)print factorial(10)import time def performance(unit):def pp(f):def ff(*a,**k): t1=time.time() r=f(*a,**k) t2=time.time()print'call %s() in %f%s'%(f.__name__,t2-t1,unit)return rreturn ffreturn pp @performance('ms')def factorial(n):return reduce(lambda x,y: x*y, range(1, n+1)) print factorial(10)由于decorator会改造函数,便会改变函数的__name__,__doc__等其他属性,所以就需要将原函数属性复制到新函数中使用functools自动化完成这个复制任务
import functoolsdef log(f):#@functools.wraps(f)def wrapper(*args,**kw):print'call...'return f(*args,**kw)return wrapper@logdef ff():return1print ff.__name__此时输出wrapper 若加上@functools.wraps(f) 输出ff
import time, functools def performance(unit):def pp(f):@functools.wraps(f)def ff(*rags,**k): t1=time.time() r=f(*rags,**k) t2=time.time()print'call %s in %f%s'%(f.__name__,t2-t1,unit)return rreturn ffreturn pp @performance('ms')def factorial(n):return reduce(lambda x,y: x*y, range(1, n+1))print factorial(10)print factorial.__name__偏函数:
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'])cmp(x,y)函数为对比函数 x>y返回1 x=y返回0 x<y 返回-1
模块和包:
包便是文件夹,.py文件便是模块,包中必须要有__init__.py文件,包的每层目录中都需要有
用import引用其他模块的函数等
将同名模块放入不同的包中
#test.pyimport p1.unitprint p1.unit.f(2,1)os.path模块提供了is.dir()和isfile()函数,判断指定目录和文件是否存在
import os.path print os.path.isdir(r'/data/webroot/resource/python')print os.path.isfile(r'/data/webroot/resource/python/test.txt')动态导入模块(动态引入需要在直接引入之前):
同样实现stringIO的功能,但是CStringIO模块部分是用c写的,所以CStringIO要比StringIO运行要快。
try:from cStringIO importStringIOexceptImportError:fromStringIOimportStringIOtry:import jsonexceptImportError:import simplejson as json print json.dumps({'python':2.7})使用import...as...动态导入不同名称的模块
使用__future__
python新版本会引入新的功能,但是,实际上这些功能再上一个老版本中已经存在,要试用某些新特性,就可以通过导入__future__模块的某些功能来实现。
from __future__ import division#若不引入,print 10/3输出3,引入输出3.3333333import p1.hello print10/3print p1.hello.factorial(10)from __future__ import unicode_literals s = b'am I an unicode?'print isinstance(s, unicode)在现在的版本中,字符串同意为unicode不需要加u前缀,而str 必须加b前缀
安装第三方模块
工具:easy_install pip(官方推荐,内置到python2.7.9)
确保python版本为python2.7.9以上版本,在命令提示符下使用pip install web.py(web.py为第三方模块)
面向对象编程
classPerson(object):pass类名首字母大写,object为该类继承的类
classPerson(object):def __init__(self,name):#构造函数 self.name=name xiaoming =Person('xiaoming')xiaohong =Person('xiaohong') print xiaoming.nameprint xiaohong.nameprint xiaoming.name==xiaohong.nameclassPerson(object):pass p1 =Person()p1.name ='Bart' p2 =Person()p2.name ='Adam' p3 =Person()p3.name ='Lisa' L1 =[p1, p2, p3]L2 = sorted(L1,lambda p1,p2:cmp(p1.name,p2.name)) print L2[0].nameprint L2[1].nameprint L2[2].namepython关键字参数和可变参数
python关键字参数用**kw表示,在调用时可以默认赋值且可以为任意个的参数
可变参数用*args表示,在调用时可以是任意个的参数
def foo1(arg1,arg2,*arg,**keywords):print"arg1 parameters is ",arg1print"arg2 parameters is ",arg2print"Arbitrary parameter is ", argprint"keywords parameter is ",keywords foo1(1,2,3,4,5,6,k1=1,k2=2,k3=3)构造函数初始化,参数是可以为关键字参数或可变参数
classPerson(object):def __init__(self,name,sex,bor,*args,**kw): self.name=name self.sex=sex self.bor=borfor k,v in kw.iteritems(): setattr(self,k,v)for c in args: setattr(self,c) xiaoming =Person('Xiao Ming','Male','1990-1-1', job='Student',job2='sty') print xiaoming.nameprint xiaoming.jobprint xiaoming.job2访问限制:
设置某属性为外部无法访问用双下划线开头 __
classPerson(object):def __init__(self, name, score): self.name=name self.__score=score p =Person('Bob',59) print p.nameprint p.__score创建类属性(不同于实例属性)
classPerson(object): count=0def __init__(self,name):Person.count=Person.count+1 self.name=name p1 =Person('Bob')printPerson.count p2 =Person('Alice')printPerson.count p3 =Person('Tim')printPerson.count当实例属性和类属性重名时,实例属性优先级高,实例中是不能修改类属性的
classPerson(object): __count =0 count=0 def __init__(self, name):Person.__count=Person.__count+1 self.name=name p1 =Person('Bob')p2 =Person('Alice') printPerson.__countprintPerson.count定义实例函数
#-*- coding:utf-8 -*- classPerson(object): def __init__(self, name, score): self.__score=score self.name=name def get_grade(self):if self.__score>=80:return'优秀'if self.__score>=60:return'及格'if self.__score<60:return'不及格' p1 =Person('Bob',90)p2 =Person('Alice',65)p3 =Person('Tim',48) print p1.get_grade()print p2.get_grade()print p3.get_grade()最上面那句是为了使其支持中文编码
方法也可以看出是属性,可以将方法动态的添加到实例上,只是需要使用types.MethodType()将一个函数变为一个方法
import typesdef fn_get_grade(self):if self.score >=80:return'A'if self.score >=60:return'B'return'C' classPerson(object):def __init__(self, name, score): self.name = name self.score = score p1 =Person('Bob',90)p1.get_grade = types.MethodType(fn_get_grade, p1,Person)print p1.get_grade()# => Ap2 =Person('Alice',65)print p2.get_grade()# ERROR: AttributeError: 'Person' object has no attribute 'get_grade'# 因为p2实例并没有绑定get_gradeclassPerson(object): def __init__(self, name, score): self.name = name self.score = score self.get_grade =lambda:'A' p1 =Person('Bob',90)print p1.get_gradeprint p1.get_grade()定义类方法,和属性相似,方法也分实例方法和类方法
classPerson(object): count=0@classmethoddef howMany(cls):return cls.countdef __init__(self,name): self.name=namePerson.count=Person.count+1printPerson.howMany()p1=Person('xiaoming')printPerson.howMany()classPerson(object): __count =0 def __init__(self,name):Person.__count=Person.__count+1 self.name=name@classmethoddef how_many(cls):return cls.__count printPerson.how_many() p1 =Person('Bob') printPerson.how_many()继承
classPerson(object): count=0@classmethoddef howMany(cls):return cls.countdef __init__(self,name,gender): self.name=namePerson.count=Person.count+1classStudent(Person):def __init__(self,name,gender,school,score): super(Student,self).__init__(name,gender) self.school=school self.score=scoreprintPerson.howMany()p1=Person('xiaoming','m')s1=Student('n','s','d',11) print s1.name printPerson.howMany()isinstance(s,type)函数,检测s是否是type类型,可用于判断属性是否是int、str等类型
classPerson(object): def __init__(self, name, gender): self.name = name self.gender = gender classStudent(Person): def __init__(self, name, gender, score): super(Student, self).__init__(name, gender) self.score = score classTeacher(Person): def __init__(self, name, gender, course): super(Teacher, self).__init__(name, gender) self.course = course t =Teacher('Alice','Female','English') print isinstance(t,Person)print isinstance(t,Student)print isinstance(t,Teacher)print isinstance(t,object)多态
classPerson(object):def __init__(self, name, gender): self.name = name self.gender = genderdef whoAmI(self):return'I am a Person, my name is %s'% self.name classStudent(Person):def __init__(self, name, gender, score): super(Student, self).__init__(name, gender) self.score = scoredef whoAmI(self):return'I am a Student, my name is %s'% self.name classTeacher(Person):def __init__(self, name, gender, course): super(Teacher, self).__init__(name, gender) self.course = coursedef whoAmI(self):return'I am a Teacher, my name is %s'% self.name def who_am_i(x):print x.whoAmI() p =Person('Tim','Male')s =Student('Bob','Male',88)t =Teacher('Alice','Female','English') who_am_i(p)who_am_i(s)who_am_i(t)其中调用whoAmI函数时,先找该对象的方法,没有再向其父类找
python提供了open()方法来打开一个磁盘文件,并返回File对象,File对象有一个read()方法可以读取文件内容
任何含有read()方法的函数都可以称为 File-like-object 都可以直接将其对象传给json.load()
import jsonclassStudents(object):def read(self):return r'["Tim", "Bob", "Alice"]'s =Students()print json.load(s)多重继承 从多个父类继承,称为多重继承
在多重继承中,父类的父类的__init__方法只会被调用一次
Python的网络服务器有TCPServer、UDPServer、UnixStreamServer、UnixDatagramServer
服务器运行模式有多进程ForkingMixin和多线程ThreadingMixin
classPerson(object):pass classStudent(Person):pass classTeacher(Person):pass classSkillMixin(object):pass classBasketballMixin(SkillMixin):def skill(self):return'basketball' classFootballMixin(SkillMixin):def skill(self):return'football' classBStudent(BasketballMixin,Student):pass classFTeacher(FootballMixin,Teacher):pass s =BStudent()print s.skill() t =FTeacher()print t.skill()获取对象信息
type(x)获取对象x的类型 dir(x)获取对象x的所有属性信息。
若知道一个属性名称,要获取或设置对象的属性,就需要用到getattr()和serattr()
#-*- coding:utf-8 -*-classPerson(object):def __init__(self, name, gender):self.name = nameself.gender = genderclassStudent(Person):def __init__(self, name, gender, score):super(Student, self).__init__(name, gender)self.score = scoredef whoAmI(self):return'I am a Student, my name is %s'% self.names =Student('Bob','Male',88)print type(s)print getattr(s,'name')print getattr(s,'age',20)#不存在age值则返回默认值20setattr(s,'name','Adam')print dir(s)
2015.8.7
特殊方法(魔术方法)
特殊方法定义的class中,不需要直接调用,Python的某些函数或操作符会调用对应的特殊方法
#-*- coding:utf-8 -*- classPerson(object):def __init__(self, name, gender): self.name = name self.gender = genders =Person('Bob','Male')print sprint s.__str__()#输出结果同上__str__()便是一个特殊方法,用于显示给用户print s.__rpr__()#用于显示给开发人员
特殊方法也可以重写
classPerson(object): def __init__(self, name, gender): self.name = name self.gender = gender classStudent(Person): def __init__(self, name, gender, score): super(Student, self).__init__(name, gender) self.score = score def __str__(self):return'Student: %s,%s,%s'%(self.name,self.gender,self.score) __repr__=__str__s =Student('Bob','male',88)print s__cmp__()方法
对于int,str等内置数据类型排序是,python的sorted()安装默认额比较函数cmp排序,但是对一组Student类的实例排序是就必须提供我们自己的特殊方法__cmp__()
classStudent(object): def __init__(self, name, score): self.name = name self.score = score def __str__(self):return'(%s: %s)'%(self.name, self.score) __repr__ = __str__ def __cmp__(self, s):if self.score<s.score:return-1elif self.score==s.score:return0else:return1 L =[Student('Tim',99),Student('Bob',88),Student('Alice',99)]print sorted(L)__len__()方法
如果类的实例想要使用len()方法必须实现__len__()方法
classFib(object): def __init__(self, num): a,b,L=0,1,[]for n in range(num): L.append(a) a,b=b,a+b self.numbers=L def __str__(self):return str(self.numbers) __repr__=__str__def __len__(self):return len(self.numbers) f =Fib(10)print fprint len(f)数学运算
有理数:有理数是一个整数a和一个非零整数b的比,例如3/8
def gcd(a,b):#处理有理数归约if b==0:return areturn gcd(b,a%b)classRational(object):def __init__(self, p, q): self.p = p self.q = q def __add__(self, r):returnRational(self.p * r.q + self.q * r.p, self.q * r.q) def __sub__(self, r):returnRational(self.p*r.q-self.q*r.p,self.q*r.q) def __mul__(self, r):returnRational(self.p*r.p,self.q*r.q) def __div__(self, r):returnRational(self.p*r.q,self.q*r.p) def __str__(self): g=gcd(self.p,self.q)return'%s/%s'%(self.p/g,self.q/g)########## __repr__ = __str__ r1 =Rational(1,2)r2 =Rational(1,4)print r1 + r2print r1 - r2print r1 * r2print r1 / r2类型转换
classRational(object):def __init__(self, p, q): self.p = p self.q = q def __int__(self):return self.p // self.q def __float__(self):return float(self.p)/self.q print float(Rational(7,2))print float(Rational(1,3))@property装饰器
classStudent(object): def __init__(self, name, score): self.name = name self.__score = score @property #如get方法def score(self):return self.__score @score.setter #如set方法def score(self, score):if score <0or score >100:raiseValueError('invalid score') self.__score = score @propertydef grade(self):if self.score<60:return'C'if self.score<80:return'B'return'A' s =Student('Bob',59)print s.grade s.score =60print s.grade s.score =99print s.grade__slots__方法控制类属性如下
classStudent(object): __slots__ =('name','gender','score')def __init__(self, name, gender, score): self.name = name self.gender = gender self.score = scores =Student('Bob','male',59)s.name ='Tim'# OKs.score =99# OKs.grade ='A'在__slots__中只定义了三个属性,所以会导致s.grade不能正常运行,只有在__slots__中定义了的属性才能够运行
classPerson(object): __slots__ =('name','gender') def __init__(self, name, gender): self.name = name self.gender = gender classStudent(Person): __slots__ =('score',)#当只有一个属性是,之后需要加个, def __init__(self,name,gender,score): super(Student,self).__init__(name,gender) self.name=name self.gender=gender self.score=score s =Student('Bob','male',59)s.name ='Tim's.score =99print s.score__call__ 将一个实例编程一个可调用对象,即时将一个实例变为一个可调用函数
classPerson(object):def __init__(self, name, gender): self.name = name self.gender = gender def __call__(self, friend):print'My name is %s...'% self.nameprint'My friend is %s...'% friendp=Person('bob','man')p('tim')classFib(object):def __call__(self,num): a,b,L=0,1,[]for n in range(num): L.append(a) a,b=b,a+breturn L f =Fib()print f(10)
浙公网安备 33010602011771号