python进阶笔记

来源:互联网 发布:流媒体服务器 linux 编辑:程序博客网 时间:2024/05/17 01:08

1、函数式编程

(1)概念





(2)高阶函数

变量名可以指向函数,函数名就是指向函数的变量

                                    


(3)map()函数     ----- python内置高阶函数,接收一个函数f 和 一个list,并通过函数f依次作用在list的每个元素上,得到一个新的list并返回


注:map()不改变原来的list,而是返回新的list


注:python2中map()函数返回一个list列表,在python3中map()返回iterator,要返回list需要list作用于map,即:list(map(f,[]))


(4)函数比较

  • capitalize() 首字母大写,其余全部小写

    upper() 全转换成大写

    lower() 全转换成小写

    title() 标题首字大写,如"i love python".title() "I love python"

(5)reduce()函数   ------ python内置的高阶函数,与map()类似,接收一个函数f 和 一个list,但reduce()传入的函数f必须接收2个参数,reduce()对list的每个元素反复调用函数f,并返回最终结果值。    ------ 对参数序列中元素进行累计

eg: from functools import reduce //reduce()函数在python3中已经从全局名字移除
def f(x,y):
    return x + y
print(reduce(f,[1,3,5,7,9]))

内部计算为:f(1,3) = 4     f(4,5) = 9     f(9,7) = 16      f(16,9) = 25

注意:reduce()还可以接收第3个可选参数,作为计算的初始值。 reduce(f,[1,3,5,7],100)   第一轮计算为:f(100,1)


(6)filter()函数   ------ python中内置的高阶函数,接收一个函数f和一个list,函数f对每个元素进行判断,返回True或False

     ------ filter()根据判断结果自动过滤不符合条件的元素,返回由符合条件元素组成的新list。

     ------- filter函数会对序列参数list中的每个元素调用f函数,最后返回的结果包含调用结果为True的元素。

注:python2中filter()函数返回一个list列表,在python3中filter()返回iterator,要返回list需要list作用于filter,即:list(filter(f,[]))


eg: 利用filter()删除None或者空字符串:



注:s.strip(rm)删除s字符串中开头、结尾处的rm序列的字符。当rm为空时,默认删除空白符(包括'\n','\r','\t',' ')


如果还不理解,可以参考:http://blog.csdn.net/damotiansheng/article/details/44139111,详细了解python3中filter()、map()和reduce()函数


(7)自定义排序函数

sorted()函数     ----- python内置的,可对list排序   也可对字符串排序

 ----- 高阶函数,可以接收一个比较函数来实现自定义排序,比较函数的定义是,传入两个待比较的元素 x, y,如果 x 应该排在 y 的前面,返回 -1,如果 x 应该排在 y 的后面,返回 1。如果 x 和 y 相等,返回 0。

自定义:eg:对字符串排序时,有时候忽略大小写排序更符合习惯。请利用sorted()高阶函数,实现忽略大小写排序的算法。

输入:['bob', 'about', 'Zoo', 'Credit']
输出:['about', 'bob', 'Credit', 'Zoo']


def cmp_ignore_case(s1, s2):
    u1 = s1.upper()
    u2 = s2.upper()
    if u1 < u2:
        return -1
    if u1 >u2:
        return 1
    return 0


print sorted(['bob', 'about', 'Zoo', 'Credit'],cmp_ignore_case)

注:Python3不支持该种方式了,所以只能写成其他方式:如:

print(sorted(['bob', 'about', 'Zoo', 'Credit'], key=str.lower))


(8)返回函数

python的函数   ----  可以返回int str list dict等数据类型,还可返回函数


eg:请编写一个函数calc_prod(lst),它接收一个list,返回一个函数,返回函数可以计算参数的乘积。

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])
print f()


(9)闭包  ----- 内层函数引用了外层函数的变量(参数也算变量),然后返回内层函数


特点:返回的函数还引用了外层函数的局部变量


(10)匿名函数  ----- 只能有一个表达式,不写return

eg: map(lambda x: x * x, [1,2,3,4,5,6])      ----- lambda x: x * x  等价于  def f(x):

return x * x

lambda  -----关键字,表示匿名函数   冒号前的x,表示函数参数


eg: sorted([1.3.9.5.0], lambda x,y:-cmp(x,y))


函数返回时也可以返回匿名函数



2、装饰器decorator  ---- 通过高阶函数返回新函数,实现装饰器,增强原有函数功能

(1)装饰器概念








装饰器的作用  -----  极大地简化代码,避免每个函数都去编写重复性代码


(2)python中编写无参数decorator  ------ 本质就是一个高阶函数,接收一个函数作参数,返回一个新函数

   ------  用@语法,可以避免手动编写 f = decorator(f) 的代码




@log ,对于一个参数的函数,工作很好,但是对于参数不是一个的函数,如add(x,y)则调用会出错

为了使@log自适应任何参数定义的函数,可以利用python的*argvs和**kw,保证任意个数的参数都能正常调用

def log(f):    def fn(*args, **kw):        print 'call ' + f.__name__ + '()...'        return f(*args, **kw)    return fn

(3)python中编写带参数decorator  ---- @log('debug')



(4)python中完善decorator



若要调用者看不出一个函数经过@decorator的改造,需把原函数的一些属性复制到新函数中

python内置的functools 可以用了自动化完成这个复制任务

import functoolsdef log(f):    @functools.wraps(f)    def wrapper(*args, **kw):        print 'call...'        return f(*args, **kw)    return wrapper

3、python中偏函数

functools.partial 即帮助创建偏函数的  --- 可以将一个参数多的函数变为一个参数少的新函数,少的参数需在创建时制定默认值


4、模块和包 

(1)概念

 包  ---- 即文件夹,包可以有多级    ---- 与普通目录的区别,包下有_init_.py,每层必须有

模块  ---- 模块即 .py文件

math中有pow\sin\cos\log等函数

os.path中提供了 isdir()和isfile()函数



try的作用是捕获错误,并在捕获到制定错误时执行except语句



(2)__future__     -----  前后的是两个连续的下标线组成

from  __future__ import division    ----- 即将python3中的除法定义引入到python2中了


python3.x中,‘/’除将得到浮点数,‘//’除才仍是整数


(3)第三方模块的安装


5、python面向对象  ----最重要的思想就是数据封装

(1)类的定义与创建  

定义:class Person(object) :    ------ 类名以大写字母开头,(object)表示该类从哪个类继承下来

pass  

创建:xiaoming = Person()    ------ 类名 + ()


(2)初始化实例属性  ------ __init__()方法:创建实例时被自动调用,第一个参数必须是self,指向调用该方法的实例本身



请定义Person类的__init__方法,除了接受 name、gender 和 birth 外,还可接受任意关键字参数,并把他们都作为属性赋值给实例

class Person(object):
    def __init__(self, name, gender, birth, **kw):
        self.name = name
        self.gender = gender
        self.birth = birth
        for k,v in kw.iteritems():
            setattr(self,k,v)



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


print xiaoming.name
print xiaoming.job


要定义关键字参数,使用 **kw

除了可以直接使用self.name = 'xxx'设置一个属性外,还可以通过 setattr(self, 'name', 'xxx') 设置属性。

(1)*argv就是可变参数元组(tuple),可以表示任何多个无名参数,它的数据结构是:元组(tuple)。

(2)**kwargv则是可变参数字典(dict),可以表示任意多个关键字参数,它的数据结构是:字典(dict)

实例的初始属性中接受一个dict,用{key,values}表示,所以job=‘Student’表示为{"job":"Student"}
可以直接使用self.name = 'xxx'设置一个属性外,还可以通过 setattr(self, 'name', 'xxx') 设置属性

**kw表示可以任意输入参数和对应的值,这些键值对被组织成字典dict,for k,v in kw.iteritems()表示对该字典的键值对进行迭代(k获得键,v获得值), iteritems()这个方法可以一个一个输出字典中的键值对,setattr(self,k,v)表示对实例自身设置属性和对应的值,self表示实例自身,k表示参数,v表示值。


(3)访问限制



如果一个属性以"__xxx__"的形式定义,那它又可以被外部访问了,以"__xxx__"定义的属性在Python的类中被称为特殊属性,有很多预定义的特殊属性可以使用,通常我们不要把普通属性用"__xxx__"定义。



虽然私有属性无法从外部访问,但是,从类的内部是可以访问的。除了可以定义实例的属性外,还可以定义实例的方法。

      get_grade(self)就是实例方法

在实例方法内部,可以访问所有实例属性,这样,如果外部需要访问私有属性,可以通过方法调用获得,这种数据封装的形式除了能保护内部数据一致性外,还可以简化外部调用的难度。


(4)创建类属性

绑定在一个实例上的属性不会影响其他实例,但是,类本身也是一个对象,如果在类上绑定一个属性,则所有实例都可以访问类的属性,并且,所有实例访问的类属性都是同一个!也就是说,实例属性每个实例各自拥有,互相独立,而类属性有且只有一份。


因为类属性只有一份,所以,当Person类的count改变时,所有实例访问到的类属性都改变了。


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


(5)方法即属性,可以通过 types.MethodType() 动态添加到实例


方法调用需要传入self,函数调用不需要传入self


(6)类方法

方法分为类方法和实例方法,在class中定义的都是实例方法,第一个参数为self即实例本身。通过@class标记定义的方法为类方法,第一个参数为cls即类本身



6、类的继承  ----代码复用

(1)概念



子类和父类是is关系

super().__init__   初始化父类


(2)类的继承

  • 一定要用 super(Student, self).__init__(name, gender) 去初始化父类,否则,继承自PersonStudent 将没有 namegender
  • 函数super(Student, self)将返回当前类继承的父类,即 Person ,然后调用__init__()方法,注意self参数已在super()中传入,在__init__()中将隐式传递,不需要写出(也不能写)
  • 函数 isinstance() 可以判断一个变量的类型,既可以用在Python内置的数据类型如str、list、dict,也可以用在我们自定义的类,它们本质上都是数据类型。

(3)多态

类具有继承关系,并且子类类型可以向上转型看做父类类型,如果我们从 Person 派生出 StudentTeacher ,并都写了一个 whoAmI() 方法:

这种行为称为多态。也就是说,方法调用将作用在 x 的实际类型上。sStudent类型,它实际上拥有自己的 whoAmI()方法以及从 Person继承的 whoAmI方法,但调用 s.whoAmI()总是先查找它自身的定义,如果没有定义,则顺着继承链向上查找,直到在某个父类中找到为止。


(4)多重继承



(5)python中获取对象信息



7、定制类

(1)python的特殊方法   ---- 定义在class中;不需直接调用;python的某些函数或操作符自动调用对应特殊方法


(2)__str__和__repr__方法



(3)__len__方法

斐波那契数列是由 0, 1, 1, 2, 3, 5, 8...构成。

请编写一个Fib类,Fib(10)表示数列的前10个元素,print Fib(10) 可以打印出数列的前 10 个元素,len(Fib(10))可以正确返回数列的个数10。




(4)

def gcd(a, b):
    if b == 0:
        return a
    return gcd(b, a % b)
    
class Rational(object):
    def __init__(self, p, q):
        self.p = p
        self.q = q


    def __add__(self, r):
        return Rational(self.p * r.q + self.q * r.p, self.q * r.q)


    def __sub__(self, r):
        return Rational(self.p * r.q - self.q * r.p, self.q * r.q)


    def __mul__(self, r):
        return Rational(self.p * r.p, self.q * r.q)


    def __div__(self, r):
        return Rational(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 + r2
print r1 - r2
print r1 * r2
print r1 / r2


(5)__slot__  ----- 一个类允许的属性列表

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





原创粉丝点击