python中0xf2_python语法笔记(二)——进阶

基于python2.7。

笔记根据廖雪峰在慕课网的课程整理而成。

一、函数式编程

函数式是一种编程范式,不需要变量,测试简单,支持高阶函数,代码简洁。python的函数式编程并不完全属于函数式,因为python允许有变量。

1、高阶函数。变量可以指向函数,通过变量将一个函数传给另一个函数。简单理解就是能接收函数做参数的函数。

import math

# 定义一个add()函数,其参数之一func用于传入一个函数名

def add(x, y, func):

return func(x) + func(y)

print add(25, 9, math.sqrt) # func变量传入sqrt()函数,实现两个数的平方根之和。结果打印出8.0

2、map()函数。map()是python内置的高阶函数,它接收一个函数func和一个list,并通过把函数func依次作用在list的每个元素上,得到一个新的list并返回。map()函数不改变原有的list,而是返回一个新的list。

注:python3中需要在map前加list才可以输出内容,否则只能输出一个map对象。

def toUpper(L):

return L[0].upper()+L[1:].lower()

listTest = ['adam', 'LISA', 'barT']

print map(toUpper, listTest) # 打印出['Adam', 'Lisa', 'Bart']

# print (list(map(toUpper, listTest))) # python3用法

3、reduce()函数。reduce()是python内置的高阶函数,接收的参数和map()类似,都是一个函数func和一个list,但reduce()传入的函数func必须接收两个参数。reduce()对list的每个元素反复调用函数func,并返回最终结果值。

注:python3中需要从functools模块导入reduce。

# from functools import reduce # python3用法

def prod(x,y):

return x*y

L = [1,2,3,4,5]

print reduce(prod, L) # 打印出120

4、filter()函数。用于过滤出符合条件的list元素,是python内置的另一个高阶函数。filter()接收一个函数func和一个list,用函数func对list的每个元素进行判断后,返回符合条件的新的list。

注:python3中需要在filter前加list才可以输出内容,否则只能输出一个filter对象。

# 判断是否为奇数

def is_odd(x):

return x % 2 == 1

L = [1,2,3,4,5,4,5,5,6,3,8,9]

print filter(is_odd, L) # 打印出[1, 3, 5, 5, 5, 3, 9]

# print (list(filter(is_odd, L))) # python3用法

5、sorted()自定义排序函数。python内置的sorted()函数可对list自定义排序,通过传入一个比较函数func,func函数里遵循大于返回1,小于则返回-1,等于则返回0的规则。另外sorted()函数也可以用于字符串的排序,默认按照ASCII的大小排序。

sorted()函数除了可以利用传入的func函数进行比较排序,还可以利用key和reverse进行排序。形式如:sorted(iterable, key = lambda x:x[y], reverse = True/False)。

def reversed_cmp(x,y):

if x > y:

return 1

elif x < y:

return -1

return 0

sorted([6, 7, 12, 7, 9, 21], reversed_cmp) # 打印出[6, 7, 7, 9, 12, 21]

# =======================================================================

L = [('b',2),('a',1),('c',3),('d',4)]

# 基于L列表每个tuple元素的索引号为1的元组进行降序排序(True为降序,False为升序),打印出[('d', 4), ('c', 3), ('b', 2), ('a', 1)]

sorted(L, key=lambda x:x[1], reverse=True)

6、返回函数。在定义的函数f()里再定义一个函数g()等,通过return返回函数g()函数。通过这种方式可以把一些计算“延迟”,这样可以在后续代码里可以决定是否需要调用该函数。

def calc_prod(lst):

def lazy_prod():

def f(x, y):

return x * y

return reduce(f, lst, 1)

return lazy_prod

f = calc_prod([1, 2, 3, 4]) # 返回函数lazy_prod(),此时并没有计算

print f() # 调用lazy_prod()函数并打印出结果24

7、序列赋值。可以在“=”两侧混合匹配序列类型,但左右两侧的数目需要一致。

listTest = ['adam', 'LISA', 'barT',3]

a,b,c,d = listTest

print a,b,c,d # 打印出“adam LISA barT 3”

8、闭包。在函数内部定义的函数和外部定义的函数是一样的,只是内部定义的无法被外部访问。如下代码所示,内部函数引用了外部函数的变量(参数也算变量),然后又return内部函数的情况,称为闭包(Closure)。

# 例1

def calc_sum(lst):

def lazy_sum():

return sum(lst)

return lazy_sum

# 例2

def count():

fs = []

for i in range(1, 4):

def f():

return i*i

fs.append(f) # 此时并没有执行函数f,添加的list元素为i*i

return fs

f1, f2, f3 = count() # 序列赋值,f1、f2、f3的值都为i*i,此时函数还没有执行

print f1(),f2(),f3() # 函数执行,此时i已循环为3,打印出“9 9 9”

9、匿名函数。匿名函数可以不必定义函数名,直接创建一个函数对象,用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]

10、装饰器decorator。其本身就是一个高阶函数。可在不改变函数体的前提下继续增加函数功能,在函数定义前使用python的“@”可以做到。

# 打印日志

def log(func):

def wrapper(*args, **kw): # “*args, **kw”可以适应任意个参数的传入

print 'call%s():' % func.__name__

return func(*args, **kw)

return wrapper

@log

def now():

print '2013-12-25'

now()

# 返回

# call now():

# 2013-12-25

11、带参数的decorator。如果希望能够通过传入参数实现decorator的不同输出,例如打印log的不同类型的信息等。

def log(text):

def decorator(func):

def wrapper(*args, **kw):

print '%s%s():' % (text, func.__name__)

return func(*args, **kw)

return wrapper

return decorator

@log('execute')

def now():

print '2013-12-25'

now()

# 打印出

# execute now():

# 2013-12-25

12、偏函数。偏函数可以设定函数参数的默认值,降低函数调用难度。python的functools模块帮助我们创建偏函数。

import functools

int2 = functools.partial(int,base=2) # 利用functools.partial创建偏函数,使得int()默认按二进制转换字符串为十进制

int2('1011011') # 返回结果91

三、模块

12、使用模块能更便捷开发,后期维护也方便,同时不同模块的同名变量互相独立。模块可用不同的包加以归类,在每个包的每个层级目录下都会有个__init__.py文件,可以让系统识别这是一个包目录而非普通目录。

import p1.util # 导入p1包目录下的util模块

print p1.util.f(2,10) # 调用p1.util模块的f函数

13、动态导入模块。利用try: ... except ImportError: ...实现动态导入。try的作用是捕获错误,并在捕获到指定错误时执行except语句。

try:

from cStringIO import StringIO # 先尝试从cStringIO导入

except ImportError:

from StringIO import StringIO # 如果从cStringIO导入失败,则从StringIO导入

14、用“__future__”实现新版本某一功能的新特性。例如python2.7整数除法的结果仍为整数,而python 3.x 对整数除法做了改进,“/”除将得到浮点数,“//”除才仍是整数。

from __future__ import division

print 10 / 3 # 打印出结果3.33333333333

print 10 / 2 # 打印出结果5.0

print 10 // 5 # 打印出结果2

15、安装第三方模块。python推荐用pip安装第三方模块,python2.7.9内置了pip,在cmd里输入需要安装的第三方名称,等待安装完成即可。

pip install web.py # 安装第三方模块web

三、面向对象编程基础

16、定义类并创建实例。通过class关键字定义,类名以大写字母开头,紧接着是(object),表示该类是从哪个类继承下来的。创建实例使用“类名()”的形式。

class Person(object): # 创建类Person

pass

xiaoming = Person() # 创建类的实例

xiaojun = Person() # 创建类的实例

print xiaoming # 打印出<__main__.person object at>

print xiaojun # 打印出<__main__.person object at>

print xiaoming == xiaojun # 比较两个实例是否相等,打印出False

17、创建实例属性。可以给每个实例创建不同的属性并给属性赋值。每个实例的属性不一定需要一致。

# 定义toLower()函数,使得传入的list元素转换为小写字母

def toLower(L):

return L[:].lower()

# 创建Person类

class Person(object):

pass

p1 = Person() # 创建类的实例p1

p2 = Person()

p3 = Person()

p4 = Person()

p5 = Person()

p6 = Person()

p7 = Person()

p1.name = 'Cjt' # 给实例p1创建name属性,并赋值

p2.name = 'zxh'

p3.name = 'syj'

p4.name = 'sfd'

p5.name = 'we'

p6.name = 'asd'

p7.name = p6.name + 'a' # 实例的属性可以像普通变量一样进行操作

# 由Person类的实例组成的list

L1 = [p1, p2, p3, p4, p5, p6, p7]

# 按实例属性值的升幂顺序排列(已转换为小写)

L2 = sorted(L1, key = lambda L1:map(toLower,L1.name), reverse=False)

print L2[0].name # 打印出“asd”

print L2[1].name # 打印出“asdaaaaa”

print L2[2].name # 打印出“Cjt”

print L2[3].name # 打印出“sfd”

print L2[4].name # 打印出“syj”

print L2[5].name # 打印出“we”

print L2[6].name # 打印出“zxh”

18、初始化实例属性。通过定义__init__()方法的函数体,在创建实例时,该方法会被自动调用。__init__()方法的第一个参数必须是 self(也可以用别的名字,但建议使用习惯用法),后续参数则可以自由指定,和定义函数没有任何区别。创建实例时,就必须要提供除self以外的参数。

class Person2(object):

def __init__(self, name, gender, birth):

self.name = name

self.gender = gender

self.birth = birth

ps1 = Person2('cjt', '男', '1993')

ps2 = Person2('zxh', '女', '1992')

ps3 = Person2('syj', '男', '1994')

print ps1.name, ps1.gender, ps1.birth #打印出“cjt 男 1993”

19、访问限制。python对属性权限的控制是通过属性名来实现的,如果一个属性由双下划线开头(__),该属性即为私有属性,无法被外部访问。

class Person3(object):

def __init__(self, name):

self.name = name

self._gender = 'Male'

self.__job = 'job'

p = Person3('bob')

print p.name # 打印出“bob”

print p._gender # 打印出“Male”。以单下划线开头的属性"_xxx"虽然也可以被外部访问,但按照习惯,他们不应该被外部访问。

print p.__job # 输出错误

20、创建类属性。如果在类上绑定一个属性,则所有实例都可以访问类的属性,并且所有实例访问的类属性都是同一个。实例属性每个实例各自拥有,互相独立,而类属性有且只有一份。访问类属性不需要创建实例,可以直接访问。对一个实例调用类的属性也是可以访问的,所有实例都可以访问到它所属的类的属性。

class Person4(object):

address = 'Earth' # 创建类属性

def __init__(self,name):

self.name = name

print Person4.address # 直接访问类属性,打印出“Earth”

pp4 = Person4('cjt')

print pp4.address # 通过实例访问类属性,打印出“Earth”

21、当实例属性和类属性重名时,实例属性优先级高,它将屏蔽掉对类属性的访问。

class Person5(object):

address = 'Earth'

def __init__(self, name):

self.name = name

p1 = Person5('Bob')

p2 = Person5('Alice')

print Person5.address # 打印出“Earth”

p1.address = 'China'

print p1.address # 打印出“China”

print Person5.address # 打印出“Earth”

print p2.address # 打印出“Earth”

22、定义实例方法。实例的方法就是在类中定义的函数,它的第一个参数永远是 self,指向调用该方法的实例本身,其他参数和一个普通函数是完全一样的。调用实例方法必须在实例上调用。在实例方法内部,可以访问所有实例属性,包括私有属性。

class Person6(object):

def __init__(self, name):

self.__name = name

def getName(self): # 定义实例方法getName()

return self.__name

pp6 = Person6('cjt')

print pp6.getName() # self不需要显式传入。打印出“cjt”

23、定义类方法。通过标记一个 @classmethod,该方法将绑定到 Person 类上,而非类的实例。类方法的第一个参数将传入类本身,通常将参数名命名为cls,例如cls.__count相当于Person.__count。

class Person(object):

__count = 0

@classmethod

def how_many(cls):

return cls.__count

def __init__(self, name):

self.name = name

Person.__count = Person.__count + 1

print Person.how_many() # 打印出0

p1 = Person('Bob')

print Person.how_many() # 打印出1

四、类的继承

24、继承一个类。在子类中,用:

super(subClass, self).__init__(ParentClassAttr1, ParentClassAttr2)

去初始化父类。

# 父类Person

class Person(object):

def __init__(self,name,gender):

self.name = name

self.gender = gender

# 子类Teacher,继承自父类Person

class Teacher(Person):

def __init__(self,name,gender,course):

super(Teacher,self).__init__(name,gender)

self.course = course

t1 = Teacher('cjt','Male','English')

print t1.name,t1.gender,t1.course #打印出“cjt Male English”

25、判断类型。isinstance()可以用来判断某个实例是否属于某个类,其会认为子类是一种父类类型,考虑继承关系。

# 父类Person

class Person(object):

def __init__(self,name,gender):

self.name = name

self.gender = gender

# 子类Teacher,继承自父类Person

class Teacher(Person):

def __init__(self,name,gender,course):

super(Teacher,self).__init__(name,gender)

self.course = course

p1 = Person('zxh','Female')

t1 = Teacher('cjt','Male','English')

print isinstance(p1,Teacher) # 打印出False

print isinstance(t1,Person) # 打印出True

26、多态。继承了父类的类,如果其和父类拥有相同的实例方法,则在调用时总是优先调用自己的方法,如果没有定义,则往父类查找。

27、多重继承。允许同时从多个父类继承,通过super()调用__init__()方法时,只需调用一次。

五、定制类

28、通过重定义特殊方法,从达到定制类的目的。如重定义__str__()方法,从而定制print打印出的内容。

class Person(object):

def __init__(self, name, gender):

self.name = name

self.gender = gender

def __str__(self):

return '(Person:%s,%s)' %(self.name, self.gender)

p = Person('Bob','Male')

print p # 打印出(Person: Bob, Male)

附:陈小挺:python语法笔记(一)——入门​zhuanlan.zhihu.com

文章首发于知乎,禁止转载。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值