python进阶知识点

1.Python支持的函数式编程

A.不是纯函数式编程:允许有变量(纯函数式编程:不需要变量,没有副作用,测试简单

B.支持高阶函数:函数可以作为变量传入

C.支持闭包:有了闭包就能返回函数

D.有限度地支持匿名函数

2.高阶函数

能接收函数做参数的函数

变量可以指向函数

函数的参数可以接受变量

一个函数可以接收另一个函数作为参数

能接收函数作参数的函数就是高阶函数

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

B.reduce()函数也是python内置的一个高阶函数,reduce()函数接收的参数和map()类似,一个函数f,一个list,但行为和map()不同,reduce()传入的函数f必须接收两个参数,reduce()list的每个元素反复调用函数f,并返回最终结果值,reduce()还可以接收第三个可选参数,作为计算的初始值.

C.filter()函数式python内置的另一个有用的高阶函数,filter()函数接收一个函数f和一个list,这个函数f的作用是对每个元素进行判断,返回True或者False,filter()根据判断结果自动过滤掉不符合条件的元素,返回由符合条件元素组成的新的list

请利用filter()过滤出1~100中平方根是整数的数,即结果应该是:

import math
def is_sqr(x):
    return math.sqrt(x)%1 == 0
print filter(is_sqr, range(1, 101))

D.sorted()函数可对list进行排序,同样也是一个高阶函数,它可以接收一个比较函数来实现自定义排序

对内容进行忽略大小写排序

def campstr(s1,s2):
    return cmp(s1.lower(),s2.lower())
print sorted(['bob', 'about', 'Zoo', 'Credit'],campstr)

3.闭包

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

Python中闭包,在函数内部定义的函数和外部定义的函数式一样的,只是无法被外部访问,如果有被定义在外函数内部的情况,并且内层函数引用了外层函数的参数,然后返回内层函数的情况,我们称为闭包.

闭包的特点是返回的函数还引用了外层函数的局部变量,所以要正确地使用闭包,就要确保引用的局部变量在函数返回后不能变.

Python中的匿名函数,高阶函数可以接收函数做参数,有些时候,我们不需要显式地定义函数,直接传入匿名函数更方便,python,对匿名函数提供了有限支持,关键字lambda表示宁明函数,冒号前面的x表示函数参数  eg: lambda x:x*x  匿名函数有一个限制,就是只能有一个表达式,不写return,返回值就是该表达式的结果

4.装饰器

Python内置的@语法就是为了简化装饰器调用

@new_fn
def f1(x):
Return x*2  
 
def f1(x):
return x*2
f1 = new_fn(f1)

作用:

可以极大地简化代码,避免每个函数编写重复性代码

打印日志:@log

检测性能:@performance

数据库事务:@transaction

URL路由:@post(‘/register’)

请编写一个@performance,它可以打印出函数调用的时间。

import time
def performance(f):
    def fn(x):
        time1 = time.time()
        val = f(x)
        print "run time = ",time.time() - time1
        return val
    return fn
 
@performance
def factorial(n):
    return reduce(lambda x,y: x*y, range(1, n+1))
 
print factorial(10)
 

5.偏函数

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

我们在sorted这个高阶函数中传入自定义排序函数就可以实现忽略大小写排序。请用functools.partial把这个复杂调用变成一个简单的函数:sorted_ignore_case(iterable)

def campstr(s1,s2):
    return cmp(s1.lower(),s2.lower())
sorted_ignore_case = functools.partial(sorted,cmp= campstr)
print sorted_ignore_case(['bob', 'about', 'Zoo', 'Credit'])

6.模块和包的概念

当代码越来越多的时候如果将所有的代码放入一个py文件:无法维护

如果将代码分拆放入多个py文件中,好处:

同一个名字的变量互不影响

引用其他的模块

#test.py ---> 自身模块名

Import math --->引用math模块

当模块多了以后,也容易重名,解决模块名冲突,只要将模块放入到不同的包中就可以解决

引用完整的模块名:

Import p1.util  

使用:

P1.util.demo()

包就是文件夹,模块名就是.py

如何区分包和普通目录:

包下面有个_init_.py这样python才会当做包来处理

动态导入模块

如果导入的模块不存在,python解释器会报ImportError错误

EG:

利用import ... as ...,还可以动态导入不同名称的模块。

Python 2.6/2.7提供了json 模块,但Python 2.5以及更早版本没有json模块,不过可以安装一个simplejson模块,这两个模块提供的函数签名和功能都一模一样。

试写出导入json 模块的代码,能在Python 2.5/2.6/2.7都正常运行。

try:
    import json
except ImportError:
    import simplejson as json
 
print json.dumps({'python':2.7})

使用__future__

Python的新版本会引入新的功能,但是,实际上这些功能在上一个老版本中就已经存在了,要试用某一新的特性,就可以通过导入__future__模块的某些功能来实现

例如:

from __future__ import division
print 10 / 3   #3.3333333333333335
print 10//3   #3

安装第三方模块

a.easy_install

b.pip(推荐,已内置到Python2.7.9)

例如安装web.py第三方模块

pip install web.py

7.Python面向对象编程

面向对象编程是一种程序设计范式

把程序看做不同对象的相互调用

对现实世界建立对象模型

基本思想

类用于定义抽象类型

实例根据类的定义被创建出来

最重要的思想:数据封装

由于Python是动态语言,对每一个实例,都可以直接给他们的属性赋值

可以给一个实例绑定很多属性,如果不希望被外部访问到,可以用__双下划线开头,该属性就无法被外部访问.但是如果一个属性以 __xxx__的形式定义,则又可以被外部访问了,__xxx__定义的属性在python的类中被称为特殊属性,有很多预定义的特殊属性可以使用,通常不把普通属性用__xxx__定义

8.类属性

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

定义类属性可以直接在class中定义

class Demo(object):
data1 = 12
Print Demo.data1

因为类属性是直接绑定在类上的,所以访问类属性不需要创建实例.

对一个实例调用类的属性也是可以访问的,所有实例都可以访问到它所属的类的属性

由于Python是动态语言,类属性也是可以动态添加和修改的...

当实例属性和类属性重名时,实例属性优先级高,它将屏蔽掉对类属性的访问。不要在实例上修改类属性,它实际上并没有修改类属性,而是给实例绑定了一个实例属性

9.实例方法

实例的方法就是在类中定义的函数,它的第一个参数永远是 self,指向调用该方法的实例本身,其他参数和一个普通函数是完全一样的:在实例方法内部,可以访问所有实例属性,这样,如果外部需要访问私有属性,可以通过方法调用获得,这种数据封装的形式除了能保护内部数据一致性外,还可以简化外部调用的难度。

class中定义的实例方法其实也是属性,实际上是一个函数对象,因为方法也是一个属性,所以它也可以动态地添加到实例上,只是需要用type.MethodType()把一个函数变为一个方法

10.类方法

和属性类似,方法也分实例方法和类方法.class中定义的全部是实例方法,实例方法第一个参数self是实例本身.通过标记@classmethod 该方法将绑定到类上,而非类的实例上,该方法的第一个参数将传入类本身,通常将参数名命名为cls,因为是在类上调用,而非实例上调用,因此类方法无法获取任何实例变量,只能获得类的引用

class Person(object):
    count = 0
    @classmethod
    def how_many(cls):
        return cls.count

11.类的继承

子类和父类是is关系,总是从某各类继承 如果没有合适的就从object继承,不能忘记调用super().__init__

如果已经定义了Person类,需要定义新的StudentTeacher类时,可以直接从Person类继承:

class Person(object):
    def __init__(self, name, gender):
        self.name = name
        self.gender = gender

定义Student类时,只需要把额外的属性加上,例如score

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

一定要用 super(Student, self).__init__(name, gender) 去初始化父类,否则,继承自 Person  Student 将没有 name  gender

函数super(Student, self)将返回当前类继承的父类,即 Person ,然后调用__init__()方法,注意self参数已在super()中传入,在__init__()中将隐式传递,不需要写出(也不能写)。

12.判断类型

函数isinstance()可以判断一个变量的类型,既可以用在Python内置的数据类型如str,list,dict,也可以用在我们自定义的类,它们本质上都是数据类型

Isinstance(“ss”,str)

继承链上,一个父类的实例不能是子类类型,因为子类比父类多了一些属性和方法,一个实例可以看成它本身的类型,也可以看成它父类的类型。

13.多态

类具有继承关系,并且子类类型可以向上转型看做父类类型,因此在实例方法的继承以及复写而言和java类似,但是bug的是因为python是动态语言,因此python在调用实例方法的时候不检查类型,只要方法存在,参数正确即可以调用.意思是:只要类中有这个方法,那么类似于这样的方法定义:

def demo(x):
x.demomethod()

只要x中有demomethod这个方法就可成功的调用demo方法.

14.多重继承

除了从一个父类继承外,python允许从多个父类继承,称为多继承

class A(object):
def __init__(self):
pass
def hi(self):
print "A hi"
pass
class B(object):
def __init__(self):
pass
def hi(self):
print "B hi"
pass
class C(A,B):
def __init__(self):
pass
 
c = C()
c.hi()

15.获取对象信息

拿到一个变量,除了用isinstance()判断是否是某种类型的实例外,可以用type()函数获取变量的类型,返回一个Type对象,也可以用dir()函数获取变量的所有属性,getattr()获取属性值,setattr()设置属性值


16.特殊方法



用于print__str__

用于len__len__

用于cmp__cmp__

特殊方法的特点

a.定义在class

b.不需要直接调用

c.某些函数或者操作符会调用对应的特殊方法

正确实现特殊方法

A.只需要编写用到的特殊方法

B.有关联性的特殊方法都必须实现

__getattr__

__setattr__

__delattr__

C.__str____repr__

如果要把一个类的实例变成str,需要实现特殊方法__str__()

__repr__()用于显示给开发人员看

D.__cmp__

int,str等内置数据类型排序时,pythonsorted()按照默认比较函数cmp排序,但是,如果对一组实例排序的时候,就必须提供自己的特殊方法__cmp__,__cmp__用实例自身self和传入的实例 s 进行比较,如果 self 应该排在前面,就返回 -1,如果 s 应该排在前面,就返回1,如果两者相当,返回 0

E.__len__

如果一个类表现的像list,要获取有多少个元素,就得用len()函数,要让len()函数工作正常,类就必须提供一个特殊方法__len__()

F.数学运算

Python提供的基本数据类型int,float可以做整数和浮点的四则运算以及乘方等运算,但是四则运算不局限于intfloat,还可以是有理数,矩阵等,要表示有理数,可以用Rational类来表示

G.类型转换

对于数据的类型转换 如下:

int(12.23)    ---- > 12
float(12)   	-----> 12.0

如果要把一个对象转换为int应该实现特殊的方法__int__()

然后调用 int(obj) 即可

Float同理类似

H.@property

class Student(object):
    def __init__(self, name, score):
        self.name = name
        self.__score = score
    @property
    def score(self):
        return self.__score
    @score.setter
    def score(self, score):
        if score < 0 or score > 100:
            raise ValueError('invalid score')
        self.__score = score

如上 可以通过对getter方法进行@progperty注解 ,这样就会将score()衍生出score属性,在调用的时候 可以通过 s.scoreget或者set

I.__slots__

如果要限制添加的属性,例如,Student类只允许添加 namegenderscore 3个属性,就可以利用Python的一个特殊的__slots__来实现。

顾名思义,__slots__是指一个类允许的属性列表:

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


现在,对实例进行操作:

>>> s = Student('Bob', 'male', 59)

>>> s.name = 'Tim' # OK

>>> s.score = 99 # OK

>>> s.grade = 'A'

Traceback (most recent call last):

  ...

AttributeError: 'Student' object has no attribute 'grade'

__slots__的目的是限制当前类所能拥有的属性,如果不需要添加任意动态的属性,使用__slots__也能节省内存。

J.__call__

一个类实例也可以变成一个可调用对象,只需要实现一个特殊方法__call__()

我们把 Person 类变成一个可调用对象:

class Person(object):
    def __init__(self, name, gender):
        self.name = name
        self.gender = gender
 
    def __call__(self, friend):
        print 'My name is %s...' % self.name
        print 'My friend is %s...' % friend

现在可以对 Person 实例直接调用:

>>> p = Person('Bob', 'male')

>>> p('Tim')

My name is Bob...

My friend is Tim...

单看 p('Tim') 你无法确定 p 是一个函数还是一个类实例,所以,在Python中,函数也是对象,对象和函数的区别并不显著。

猜你喜欢

转载自blog.csdn.net/weixin_37699212/article/details/73735258