知识点概要:
- 函数式编程(高阶函数、闭包、匿名函数、装饰器)
- 模块和包(模块、包)
- 面向对象编程(类、实例、属性、方法)
- 类的继承(目的、多态、多重继承)
- 定制类(目的、方法、call)
1.课程介绍
2.函数式编程
(1) map函数 map(f,L):
通过把函数 f 依次作用在L( L是list) 的每个元素上,得到一个新的 list 并返回;
例子:
def f(x):
return x*x
print map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9])
(2) reduce函数 reduce(f,L):
reduce()传入的函数f必须接收两个参数,reduce()对list的每个元素反复调用函数f,返回值。
例子:print (reduce(f, [1, 3, 5, 7, 9])) out:16
1+3=4
4+5=9
9+7=16
(3) filter函数 filter(f,L):
filter()函数接收一个函数f和一个list,这个函数f的作用是对每个元素进行判断
返回True或False,返回为True的。
例子:用filter()过滤出1~40中平方根是整数的数,即结果应该是:[1, 4, 9, 16, 25, 36]
import math
def is_sqr(x):
return math.sqrt(x)%1 == 0
print filter(is_sqr, range(1, 41))
(4) 排序:sorted(L):将list中的元素从小到大排序。
sorted(L,f):将list中的元素按照f中的排序方法排序。
ps:比较函数f的定义是,传入两个待比较的元素 x, y,如果 x 应该排在 y 的前面,返回 -1,如果 x 应该排在 y 的后面,返回 1。如果 x 和 y 相等,返回 0。
例子:对字符串排序,忽略大小写
输入:['bob', 'about', 'Zoo', 'Credit']
输出:['about', 'bob', 'Credit', 'Zoo']
def cmp_ignore_case(s1, s2):
if s1.lower() < s2.lower():
return -1
if s1.lower() > s2.lower():
return 1
return 0
print sorted(['bob', 'about', 'Zoo', 'Credit'], cmp_ignore_case)
###
s.capitalize() #首字母大写
s.upper()#转大写
s.lower()#转小写
(5) 返回函数:返回函数可以把一些计算延迟执行,我们可以在后续代码里,决定到底要不要调用该函数。
例子:返回函数计算参数乘积
def calc_prod(lst):
def cal():
return reduce(lambda x,y:x*y,lst)
return cal
f = calc_prod([1, 2, 3, 4]) #返回一个函数f
print f() #调用该函数
(6)闭包:内层函数引用了外层函数的变量(参数),然后返回内层函数的情况,称为闭包。
ps:使用闭包时要确保引用的局部变量在函数返回后不能变。
举例如下:
# 希望一次返回3个函数,分别计算1x1,2x2,3x3:
def count():
fs = []
for i in range(1, 4):
def f():
return i*i
fs.append(f)
return fs
f1, f2, f3 = count() #但是实际结果全为9,因为当count()函数返回了3个函数时,这3个函数所引用的变量 i 的值已经变成了3
##修改如下:输出1,4,9
def count():
fs = []
for i in range(1, 4):
def f(i): #
return lambda:i*i
fs.append(f(i))
return fs
f1, f2, f3 = count()
print f1(), f2(), f3()
(7) 匿名函数 lambda
sorted([1, 3, 9, 5, 0], lambda x,y: -cmp(x,y))
# result:[9, 5, 3, 1, 0]
(8) 装饰器 (略)
3.模块和包
- 包:相当于文件夹,与目录不同的是:包里必须有__init__.py文件,即使该文件是空的
- 模块:相当于.py文件
导入模块:import util
导入模块中部分函数:import util.f1
动态导入模块:(解决版本不对应等问题)
try:
from cStringIO import StringIO
except ImportError:
from StringIO import StringIO
4.面向对象编程
类:people
实例:XiaoMing,XiaoHong,,,
(1)创建类&实例化对象
# 创建Person类
class Person(object):
pass
# 实例化出两个对象
xiaoming = Person()
xiaohong = Person()
(2) 实例属性
#当创建实例时,__init__()方法被自动调用,我们就能在此为每个实例都统一添加属性。
class Person(object):
#self表示该实例本身,name和gender是该实例的属性
def __init__(self, name, gender):
self.name = name
self.gender = gender
xiaoming = Person('Xiao Ming', 'Male')
xiaohong = Person('Xiao Hong', 'Female')
##初始化 多参数的实例属性
class Person(object):
def __init__(self,name,**kw):
self.name = name
for k,v in kw.items():
setattr(self,k,v)
(3) 类属性
class Person(object):
address = 'Earth'
def __init__(self, name):
self.name = name
调用:Person.address
类属性特点:
1.实例属性每个实例各自拥有,互相独立,而类属性有且只有一份。
2.访问类属性不需要创建实例,就可以直接访问
3.类属性也是可以动态添加和修改的
4.当实例属性和类属性重名时,实例属性优先级高,它将屏蔽掉对类属性的访问。
(4)属性访问限制
class Person(object):
def __init__(self, name):
self.name = name
self.__job = 'Student'
#self.__XX 该属性只能在类的内部直接访问,类似于C++中的private成员
p = Person('Bob')
print p.name #Bob
print p.__job #AttributeError: 'Person' object has no attribute '__job'
(5) 实例的方法
实例的方法就是在类中定义的函数,
它的第一个参数永远是self,指向调用该方法的实例本身,其他参数和一个普通函数是完全一样的。
ps:如果外部需要访问实例的私有属性,可以通过实例的方法来实现
例子:
class Person(object):
def __init__(self, name, score):
self.name = name
self.__score = score #实例的私有属性
def get_grade(self): #实例的方法,self表示该实例
if self.__score >= 90:
return 'A'
elif self.__score < 60:
return 'C'
else:
return 'B'
p1 = Person('Bob', 90)
p2 = Person('Alice', 65)
p3 = Person('Tim', 48)
#get_grade() 中的 self不需要显式传入,但括号不可丢
print p1.get_grade() #->A
print p2.get_grade() #->B
print p3.get_grade() #->C
(6) 类方法
class Person(object):
count = 0 #类属性
@classmethod #标记一个 @classmethod,表示how_many是类的一个方法,而不是实例
def how_many(cls): #类方法的第一个参数将传入cls,表示该类。相当于实例中的self。
return cls.count #cls.count等价于Person.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
5.类的继承
目的:代码复用
(1) 类继承特点
- 类总是要从某个类继承的,没有合适的就从 object类中继承
class MyClass(object):
pass
- 有合适的类继承要调用super,否则找不到父类的存在的属性
class Student(Person):
def __init__(self,args):
super(Student,self).__init__(args)
pass
例子:
class Person(object):
def __init__(self, name, gender):
self.name = name
self.gender = gender
class Teacher(Person):#继承父类Person
def __init__(self, name, gender, course):
super(Teacher,self).__init__(name,gender)#继承父类属性初始化
self.course = course #补充缺少的属性
t = Teacher('Alice', 'Female', 'English')
print t.name
print t.course
#dir(s):获取变量的所有属性。
#getattr(s, attr_key) # 获取name属性
#setattr(s, attr_key, attr_value) # 设置新的name属性
(2) 多态:
父类和继承子类都有相同方法 称为 多态
如:从 Person 派生出 Student和Teacher ,并都写了一个 whoAmI() 方法
"""
注意:
假如s 是Student类型,它实际上拥有自己的 whoAmI()方法以及从 Person继承的whoAmI方法,
但调用 s.whoAmI()总是先查找它自身的定义,如果没有定义,则顺着继承链向上查找,直到在
某个父类中找到为止。
"""
6.定制类(python中常见的特殊方法)
目的:使得编写的类可以应用到普通的函数中
(1) __str__ 和 __repr__
把一个类的实例变成 str,就需要实现特殊方法__str__()。
"""
__str__()方法:用于显示给用户(print p)
__repr__()方法:用于显示给开发人员(直接调用的:p)。
"""
例子:
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)
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)
__repr__ = __str__ ####
p = Person('Bob', 'male')
>>>p -> (Person: Bob, male)
(2) __cmp__ 类的实例排序
例子:分数从高到底排序&分数相同按照 人名
class Student(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):#__cmp__用实例自身self和传入的实例 s 进行比较
#if False == isinstance(s, Student):
#return -1
return -cmp(self.score, s.score) or cmp(self.name, s.name)
L = [Student('Tim', 99), Student('Bob', 88), Student('Alice', 99)]
print sorted(L) # ->[(Alice: 99), (Tim: 99), (Bob: 88)]
(3) __len__
class Students(object):
def __init__(self, *args):
self.names = args
def __len__(self):
return len(self.names)
>>> ss = Students('Bob', 'Alice', 'Tim')
>>> print len(ss)
3
(4) __call__
在Python中,函数其实是一个对象,所有的函数都是可调用对象。
一个类实例也可以通过使用__call__变成一个可调用对象。
例子:斐波那契数列
class Fib(object):
def __init__(self):
pass
def __call__(self,num):
lis = [0]*num
lis[1] = 1
for i in range(2,num):
lis[i] = lis[i-1] + lis[i-2]
return lis
f = Fib()
print f(10)