内容基本上来自于廖雪峰老师的blog相当于自己手打了一遍,加强加强理解吧。

http://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000

Python的一些高级特性

Slot

python是动态语言,所谓动态,就是可以先创建类的实例,之后再动态绑定属性或方法,比如下边这个例子:

class Student(object)

pass

s=Student()

s.name="asd"

注意这里的pass就是相当于空语句,表示什么都不做。

还可以进行方法的动态绑定,比如定义下面的方法,有点像java中反射的感觉。

def set_age(self,age)

self.age=age

from types import MethodType

s.set_age=MethodType(set_age,s,Student)

其中三个形参的含义:

将已经定义好的 set_age方法,绑定在Student类的实例s上。

绑定的时候,仅仅是将set_age方法与实例s进行了绑定,这里的绑定,只能是与固定实例进行,要是通过s2=Student() s2.set_age()来进行方法调用,就是不起作用的,因为方法仅仅与s1实例进行了绑定。

如果希望使得所有的类都适用,需要给class类绑定类方法:

def set_score(self,score)

self.score=score

Student.set_score=MethodType(set_score,None,Student)

这里的None表示这个类还没有实例

注意前面的不同,这里再具体进行绑定的时候,前面直接写成了,类名.set_score的形式。

实际情况中,有些时候,并不希望对实例的任意绑定都能够进行,这样随随便便就进行绑定想来也总是不太安全的行为。

可以通过下面的方法来解决:在定义class的时候,通过添加__slot__变量,来限制该class类所能够添加的属性。

class Student(object)

__slot__=('name','age')

注意通过__slot__定义仅对当前的类起作用,对继承的子类是不起作用的。

除非在子类中也加上__slot__ ,这样就相当于子类的__slot__范围加上父类的__slot__范围。

这样的话,能动态绑定的属性,就只有name和age两个。

如果绑定一个超出__slot__中所限制的范围的属性进去,比如:

s=Student()

s.score=90

这样就会报错。

函数式编程以及高阶函数

所谓高阶函数,就是函数本身也能作为参数传入,很多语言中都有高阶函数的相关机制。

能接受一个函数作为传递参数的函数,就称为高阶函数,所谓的函数式编程,就是指在程序中使用这种更高抽象程度的编程范式。

比如MapReduce中的map函数

map(f,[1,2,3,4,5])

这个就是说把f 函数作用于[1,2,3,4,5]中的每个元素,当然也可以通过别的方式来执行类似的操作,比如把list循环一下,每个元素都作为参数传递给f 最后输出的结果,

之后再放在一个新的list当中,但是这样并不是太简洁。

map作为一个高阶函数,事实上是把运算规则抽象化了,想想,有点想泛函分析的感觉,就是某种更高程度的抽象,像是直接提炼了算子出来的那种。估计自己以后不太有机会学数学上更高程度的课程了,想想当初老师上课说,如果工科方面再往高学,泛函分析是必须要学的,想想有点可惜,题外话。

运算规则抽象之后,不但可以对简单的f(x)=x^2计算,还可以按照算子的计算规则,对序列或者是矩阵,进行类似的运算,确实方便好多。

reduce也是一个高阶函数,对于reduce而言,reduce可以把一个函数作用在一个序列[x1, x2, x3...]上,这个函数必须接收两个参数,reduce把当前这一步的结果继续和序列的下一个元素做累积计算,其效果就是:reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)

比方说一个序列求和的reduce的实现:

def add(x,y)

return x+y

reduce(add,[1,3,5,7,9])

这样,返回结果是25。

感觉高阶函数的主要好处还是体现在数学性比较强的运算上,比如结合mapreduce把str转化为int:

def fn(x,y)

return x*10+y

def char2num(s)

return {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}[s]

reduce(fn,map(char2num,'13579'))

先用map函数把序列中的每个元素转化为实际的数字,返回的结果可能是一个数字的列表之后再用fn函数进行数字结果的reduce操作,不断向后进行迭代每次都是之前得到的结果乘以10再加上后面的一个数字,这样不断进行累计,最后可以把分散的数字序列拼成一个实际的数字。

函数式编程在排序算法中的应用:

这个算是比较典型的,将比较结果抽象出来:两个元素x y进行比较,如果返回-1 x<y 返回0, x==y ,反之 x>y。

因此这个排序的函数也是一个高阶函数,因为在它的参数中,可以传入一个 函数,这个函数的作用是用来进行比较。

这个其实有点像模板方法模式,高级函数中定义好更高层次的函数的执行顺序,之后在调用的时候,将具体的执行函数传入。

当然,高阶函数除了接受函数作为传递的参数之外,还可以将函数作为值来返回。

比如下面的代码,在一个函数的内部又定义了另外一个求和的函数,并且将这个求和的函数返回:

def lazy_sum(*args):

def sum():

ax=0

for n in args:

ax=ax+n

return ax

return sum

调用f=lazy_sum(1,2,3,4,5)的时候,返回的只是函数的一个句柄:

只有再继续执行f()才能返回最后的结果:15。

还有一个地方要注意的是:

每次一个新的调用f1=lazy_sum(1,2,3) f2=lazy_sum(1,2,3) print f1==f2 结果就会返回false,f1()与f2()是两个不同的调用

匿名函数

匿名函数往往通过 Lambda表达式的方式来引入:

关键字lamda表示的是匿名函数,冒号前面的x表示的是函数的参数。

如果定义一个lamda x:x*x实际上表示的就是:

def f(x)

return x*x

匿名函数有一个限制,就是不用写return 这个表达式的返回值,就是最后的返回值。

用匿名函数的好处是,因为函数没有名字,因此不必担心命名冲突。

此外,匿名函数也是一个函数的对象,也可以把匿名函数赋值给一个变量,再利用变量来调用该函数。

当然通过lamda表达式定义的匿名函数也可以作为返回值来进行返回:

def build(x,y)

return lambda: x*x + y*y

注意这里lamda表达式本身就是写在函数里面的,因此就不用再在:的前面把x,y再当做函数参数进行声明了

装饰器

本质上decorator就是一个返回高阶函数的函数。

可以通过动态的方式给原来的函数添加新的功能,比如打印日志

比如我们定义一个log装饰器 对func方法进行包装

def log(func):

#这里添加了新的功能之后又将原来的函数返回

def wrapper(*args,**kw):

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

return func(*args,**kw)

return wrapper

利用python的 @ 语法 把decorator置于函数的定义处 这里大概的意思就是把下面的函数作为参数 传入之前定义好的log函数中

这里相当于执行了类似下面的函数:now=log(now)原本的now函数还是存在的 只是现在同名的now变量指向了一个新的函数

再次调用now()的时候 返回的是wrapper函数 此时now.__name__就是wrapper而不是now(这里要特别注意)

@log

def now():

print '2014-12-06'

调用now()

打印的结果如下:

call now():

2014-12-06

如果在decorator本身需要参数 就需要写一个返回decorator的参数 而不是一个仅仅返回wrapper的参数

就是在wrapper的外层多套了一层decorator 这里要连续返回两层

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=log('execute')(now)

首先调用log('execute') 返回的是最外层的decorator函数 对log可见的是这个返回的decorator函数

之后再调用这个返回的decorator函数 就是调用decorator(now) 来执行对应的wrapper函数

此时now.__name__就变成了wrapper

注意不论是两层还是三层 最里边总是一个wrapper的函数

一个完整的decorator的写法:

import functools

def log(func)

@functools.wraps(func)

def wrapper(*args,**kw)

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

return func(*args,**kw)

return wrapper

对于带参数的wrapper

import functools

def log(text):

def decorator(func):

@functools.wraps(func)

def wrapper(*args, **kw):

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

return func(*args, **kw)

return wrapper

return decorator

关键是要注意在wrapper的前面加上@functools.wrap(func)

??这里还是有一些疑问的

偏函数

这里的偏函数和数学上的偏函数概念有所不同

偏函数这个理解起来其实也比较容易

就是函数中的某些参数被设定了默认值

比如int ('12345',base=10)

要是第二个参数没有显式地传进来的话 就是默认使用base=10来进行操作

Python的一些高级特性的更多相关文章

  1. Python:笔记(4)——高级特性

    Python:笔记(4)——高级特性 切片 取一个list或tuple的部分元素是非常常见的操作.Python提供了切片操作符,来完成部分元素的选取 除了上例简单的下标范围取元素外,Python还支持 ...

  2. Python面向对象编程高级特性

    ***这里还是根据网上资料,主要是廖雪峰老师的教程学习的笔记,主要介绍python面向对象的高级特性,笔记不全,只是记录自己觉得容易出错的地方*** 1.python作为一种动态语言,他的动态绑定机制 ...

  3. Python的一些高级特性以及反序列化漏洞

    0x01 简述 文章主要记录一下python高级特性以及安全相关的问题 python作为脚本语言,其作为高级语言是由c语言开发的,关于python的编译和链接可以看向这里https://github. ...

  4. python 9学习 高级特性

    高级特性 掌握了Python的数据类型.  语句      和函数,基本上就可以编写出很多有用的程序了. 比如构造一个1, 3, 5, 7, ..., 99的列表,可以通过循环实现: L = [] n ...

  5. python:函数的高级特性

    很多语言中,都允许把函数本身做为参数,传递给其它参数:即所谓的高阶函数.python中也有类似特性: 一.map/reduce.filter.sorted hadoop里的map-reduce思想在p ...

  6. Python中的高级特性

    1.切片.使用“[”和“]”即可,类似Matlab,可以切list,tuple,字符串等. 2.迭代.Python内置的enumerate函数可以把一个list变成索引-元素对. 3.列表生成式.列表 ...

  7. Python语言的高级特性

    函数式编程 基于lambda演算的一种编程方式 函数中只有函数 函数可以作为参数,同样可以作为返回值 纯函数式编程语言:LISP , Haskell python函数式编程只是借鉴函数式编程的一些特点 ...

  8. Python快速学习-高级特性

    1.切片 取一个list或tuple的部分元素是非常常见的操作 L = ['hello','the','world','and','my','love'] 取前三个元素 L[0:3],L[:3] 取倒 ...

  9. Python学习之高级特性

    切片 在Python基础篇里,我们知道Python的可序列对象可以通过索引号(下标)来引用对象元素,索引号可以由0开始从左向右依次获取,可以从-1开始由右向左获取.这种方法可以帮助我们依次获取我们想要 ...

随机推荐

  1. VBA中Let与Set的区别

    Let与Set的区别 1.在“类模块”中 Property Let 语句 在Class块中,是给普通变量进行赋值操作的Property,该种Property将不能在其前面使用Set,因而将不能用户对对 ...

  2. 详解 vue 双向数据绑定的原理,并实现一组双向数据绑定

    1:vue 双向数据绑定的原理: Object.defineProperty是ES5新增的一个API,其作用是给对象的属性增加更多的控制Object.defineProperty(obj, prop, ...

  3. 安装kali linux 后出现文字乱码问题

    在安装kali时我选择中文安装,结果安装完成后出现文字乱码现象 在经过上网查询后,采用了CSDN博客站中的 stubbornness1219 这位博主的解决方案成功将问题解决. 解决方案:终端下执行s ...

  4. tar shell zip

    tar          打包后生成的文件名全路径                    要打包的目录 tar -czPf xx/script.tar.gz                      ...

  5. 14DBCP连接池

    实际开发中“获得连接”或“释放资源”是非常消耗系统资源的两个过程,为了解决此类性能问题,通常情况我们采用连接池技术,来共享连接Connection.这样我们就不需要每次都创建连接.释放连接了,这些操作 ...

  6. 2018-09-10-weekly

    Algorithm 删除链表的倒数第N个节点 What:给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点. How:这是一道典型的利用双指针法解题.首先让指针first指向头节点,然后 ...

  7. Altium Designer 19 导出光绘文件

    一.点击 文件--制造输出--Gerber Files 第一次设置如下 绘制层点击进去全选 钻孔光圈 符号大小50mil 生成文件 关闭不用保存 蚀刻图 二.点击 文件--制造输出--Gerber F ...

  8. Ts 的类

    TS 中的公共.私有和受保护的修饰符: 1.public表示公共的,用来指定在创建实例后可以通过实例访问的,也就是类定义的外部可以访问的属性和方法.默认是 public 2.private修饰符表示私 ...

  9. layer-框架使用修改部分

    关于框架中js调子方法出错的处理 top.layer.open({ id: options.id, type: 2, shade: options.shade, title: options.titl ...

  10. vue开发可复用组件

    组件,是一个具有一定功能,且不同组件间功能相对独立的模块.高内聚.低耦合.   开发可复用性的组件应遵循以下原则:   1.规范化命名:组件的命名应该跟业务无关,而是依据组件的功能命名. 2.数据扁平 ...