Python进阶(廖雪峰老师)

Python进阶

函数式编程、模块、面向对象编程、定制类

函数式编程
  1. 把计算视为函数而不是一系列的指令
  2. 纯函数式编程:不需要变量,没有副作用,测试简单
  3. 支持高阶函数,代码简洁
python支持的函数式编程
  1. 不是纯函数式编程:允许有变量
  2. 支持高阶函数:函数也可以作为变量传入
  3. 支持闭包:有了闭包就能返回函数
  4. 有限度的支持匿名函数
高阶函数
  1. 变量可以指向函数
#求-10的绝对值
abs(-10)
#等价于如下,定义一个变量f
f = abs
f(-10)
  1. 函数名其实就是指向函数的变量
abs = len
abs([1,2,3])
#输出就是3,abs就指向了len函数对象

高阶函数:能接收函数做参数的函数

  • 变量可以指向函数
  • 函数的参数可以接收变量
  • 一个函数可以接受另外一个函数作为参数
  • 能接收函数做参数的函数就是高阶函数
#例子利用add(x,y,f)函数计算绝对值x+绝对值y
def add(x,y,f):
    return f(x)+f(y)
    
print add(-5,9,abs)
#打印出的结果是14

Python中内置的高阶函数:

  • map()函数:
    接收一个函数 f 和一个 list,把函数 f 依次作用在list的每个元素上,得到一个新的list 并返回。
    注:map不改变原有的list,而是返回一个新的list
#例子
def f(x):
    return x*x
print map(f,[1,2,3])
#打印结果是:[1,4,9]
  • reduce()函数:
    接收一个函数 f ,一个list,reduce()传入的函数f必须接收两个参数,reduce()对list的每个元素反复调用 f ,并返回最终的结果值。
#例子
def f(x,y):
    return x+y
print reduce(f,[1,2,3])
#结果是6
  • filter()函数:
    接收一个函数 f 和一个list,这个函数f的作用是对每个元素进行判断,filter()将依据判断结果自动过滤掉不符合条件的元素,返回值由符合条件的元素组成新的list。
#例子,从一个list里面删除偶数,保留奇数
def is_odd(x):
    return x % 2 == 1
print filter(is_odd,[1,2,4,5])
#输出结果为:[1,5]
  • Python中的返回函数

Python中的函数不仅可以返回int,str,list,dict等数据类型,还可以返回函数

#例子:编写一个函数calc_prod(list),它接收一个list,返回一个函数,返回函数可以计算参数的乘积
def calc_prod(list):
    def lazy_calc():
        def f(x,y):
            return x*y
        return reduce(f,list,1)
    return lazy_calc

f = calc_prod([1,2,3]) #仅仅是返回了函数
print f()  #对返回的函数进行了调用,才返回了结果    
  • 闭包:
    内层函数引用了外层函数的变量(参数也算变量),然后返回内层函数的情况,称为闭包(closure)
    闭包的特点是返回的函数还引用了外层函数的局部变量,所以要正确的使用闭包,就要保证引用的局部变量在函数返回后不能变。
  • 匿名函数:
    高阶函数可以接收函数做参数,有时候不需要显式地定义函数,直接传入匿名参数更方便。
    关键字 lambda表示匿名函数,冒号前面的x表示函数参数
#举例子
map(lambda x : x*x,[1,2,3])
#得到的结果是[1,4,9]
decorator装饰器

起因:定义了一个函数,想在运行时动态增加功能,又不想改动函数本身的代码
python内置的@语法就是为了简化装饰器调用

#例子
@new_fn
def f1(x):
    return x*2
#等价于如下
def f1(x):
    return x*2
f1 = new_fn(f1)

装饰器的作用:可以极大地简化代码,避免每个函数编写重复的代码

  1. 打印日志:@log
  2. 检测性能:@performance
  3. 数据库事务:@transaction
  4. URL路由:@post(’/register’)
python中的偏函数

当一个函数有很多参数的时候,调用者就需要提供多个参数,如果减少参数个数,就可以简化调用者的负担。

#例子
int('12345')
#输出是12345
#int()函数还提供额外的base参数,more职位10
int('12345',16)
#输出是74565

functools.partical就是帮助我们创建一个偏函数的:

#直接使用下面代码创建一个int2()
import functools
int2 = functools.partial(int,base=2)
模块和包

为解决模块名冲突,python将同名的模块放入不同的包中,模块就是一个个.py文件。
在文件系统中,包就是文件夹,模块就是xxx.py文件,包可以有多级

  • 如何区分包和普通的目录:
    包下面有个__init__.py文件 (注意每层包都有该文件)

python导入模块:使用import语句导入一个模块
python提供的模块管理工具:easy_install、pip(可以使用二者来安装最新版的模块)

python面向对象编程

类和实例:
类用于定义抽象类型(class来定义类);
实例根据类的定义被创建出来。

  • 定义类并创建实例:
#定义一个类(括号中表示该类是从哪个类继承下来的)
#定义类并创建实例
class Person(object):
    pass

xiaoming = Person()
xiaohong = Person()
print xiaoming
print xiaohong
print xiaoming==xiaohong
  • 创建实例属性:
#创建实例属性
class Person(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].name
print L2[1].name
print L2[2].name
  • 初始化实例属性:
#初始化实例属性
class Person(object):
#记住self,个人理解像Java和c++中的this
    def __init__(self,name,sex,date,job):
        self.name=name
        self.sex=sex
        self.date=date
        self.job=job

xiaoming = Person('Xiao Ming', 'Male', '1990-1-1', job='Student')

print xiaoming.name
print xiaoming.job
  • 访问限制:
    Python对属性权限的控制是通过属性名来实现的,如果一个属性由双下划线开头(__),该属性就无法被外部访问。
#例子
class Person(object):
    def __init__(self, name, score):
        self.name=name
        self.__score=score

p = Person('Bob', 59)

print p.name
print p.__score
  • 创建类属性:
    由于Python是动态语言,类属性也是可以动态添加和修改的。
#创建count属性,每创建一个实例count属性就+1
class Person(object):
    count=0
    def __init__(self,name):
        Person.count=Person.count+1
        self.name=name

p1 = Person('Bob')
print Person.count
p2 = Person('Alice')
print Person.count
p3 = Person('Tim')
print Person.count
  • 定义实例的方法:
#请给 Person 类增加一个私有属性 __score,表示分数,再增加一个实例方法 get_grade(),能根据 __score 的值分别返回 A-优秀, B-及格, C-不及格三档。
class Person(object):
    def __init__(self, name, score):
        self.__name=name
        self.__score=score

    def get_grade(self):
        if self.__score >=80:
            return 'A'
        if self.__score >=60:
            return 'B'
        return 'C'

p1 = Person('Bob', 90)
p2 = Person('Alice', 65)
p3 = Person('Tim', 48)
print p1.get_grade()
print p2.get_grade()
print p3.get_grade()
  • 定义类方法:
#如果将类属性 count 改为私有属性__count,则外部无法读取__score,但可以通过一个类方法获取,请编写类方法获得__count值。
#注意类方法需要添加 @classmethod
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()
p1 = Person('Bob')
print Person.how_many()
类的继承

继承:新类不必重头编写;新类从现有的类继承,就自动地拥有了现有类的所有功能;新类只需要编写现有类缺少的新功能。

  • python中继承一个类:
class Person(object):
    def __init__(self, name, gender):
        self.name = name
        self.gender = gender

class Teacher(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
  • python中多重继承
    除了从一个父类继承外,python允许从多个父类继承,称为多重继承。
    python允许多重继承
定制类
  • 特殊方法:
    特殊方法定义在class中,不需要直接去调用,python的某些函数或操作符会调用对应的特殊方法。
  • 特殊方法__str__()和__repr__()
#请给Student 类定义__str__和__repr__方法,使得能打印出<Student: name, gender, score>
class Person(object):
    def __init__(self, name, gender):
        self.name = name
        self.gender = gender

class Student(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__
#请修改 Student 的 __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):
        if self.score==s.score:
            return cmp(self.name,s.name)
        return -cmp(self.score,s.score)

L = [Student('Tim', 99), Student('Bob', 88), Student('Alice', 99)]
print sorted(L)
  • 特殊方法__len__
#斐波那契数列是由 0, 1, 1, 2, 3, 5, 8...构成。
#请编写一个Fib类,Fib(10)表示数列的前10个元素,print Fib(10) 可以打印出数列的前 10 个元素,len(Fib(10))可以正确返回数列的个数10。
class Fib(object):
    def __init__(self, num):
        self.lst=[0,1]
        for i in range(2,num):
            self.lst.append(self.lst[i-2]+self.lst[i-1])
    def __str__(self):
        return str(self.lst)    
    __repr__=__str__    
    def __len__(self):
        return len(self.lst)

f = Fib(10)
print f
print len(f)
  • 特殊方法__slots__
    如果要限制添加的属性,例如,Student类只允许添加 name、gender和score 这3个属性,就可以利用Python的一个特殊的__slots__来实现。
#假设Person类通过__slots__定义了name和gender,请在派生类Student中通过__slots__继续添加score的定义,使Student类可以实现name、gender和score 3个属性
class Person(object):
    __slots__ = ('name', 'gender')
    def __init__(self, name, gender):
        self.name = name
        self.gender = gender

class Student(Person):
    __slots__ = ('score',)
    def __init__(self,name,gender,score):
        super(Student,self).__init__(name,gender)
        self.score=score

s = Student('Bob', 'male', 59)
s.name = 'Tim'
s.score = 99
print s.score
  • 特殊方法__call__
    你无法确定 p 是一个函数还是一个类实例,所以,在Python中,函数也是对象,对象和函数的区别并不显著。
#改进一下前面定义的斐波那契数列:
#class Fib(object):
#    ???
#请加一个__call__方法,让调用更简单:
#>>> f = Fib()
#>>> print f(10)
#[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
class Fib(object):
    def __call__(self,num):
        self.lst=[0,1]
        for i in range(2,num):
            self.lst.append(self.lst[i-1]+self.lst[i-2])
        return self.lst

f = Fib()
print f(10)
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值