一、偏函数
Python的functools模块提供了很多有用的功能,其中一个就是偏函数(Partial function)。要注意,这里的偏函数和数学意义上的偏函数不一样。
在介绍函数参数的时候,我们讲到,通过设定参数的默认值,可以降低函数调用的难度。而偏函数也可以做到这一点。举例如下:
int()函数可以把字符串转换为整数,当仅传入字符串时,int()函数默认按十进制转换:
>>>int('12345')12345
但int()函数还提供额外的base参数,默认值为10。如果传入base参数,就可以做N进制的转换:
>>>int('12345', base=8)5349
>>>int('12345',16)74565
假设要转换大量的二进制字符串,每次都传入int(x, base=2)非常麻烦,于是,我们想到,可以定义一个int2()的函数,默认把base=2传进去:
defint2(x, base=2):
returnint(x, base)
这样,我们转换二进制就非常方便了:
>>>int2('1000000')64>>>int2('1010101')85
functools.partial就是帮助我们创建一个偏函数的,不需要我们自己定义int2(),可以直接使用下面的代码创建一个新的函数int2:
>>>importfunctools>>>int2 = functools.partial(int, base=2)>>>int2('1000000')64>>>int2('1010101')85
所以,简单总结functools.partial的作用就是,把一个函数的某些参数给固定住(也就是设置默认值),返回一个新的函数,调用这个新函数会更简单。
注意到上面的新的int2函数,仅仅是把base参数重新设定默认值为2,但也可以在函数调用时传入其他值:
>>>int2('1000000', base=10)1000000
最后,创建偏函数时,实际上可以接收函数对象、*args和**kw这3个参数,当传入:
int2 = functools.partial(int, base=2)
实际上固定了int()函数的关键字参数base,也就是:
int2('10010')
相当于:
kw = { base:2}int('10010', **kw)
当传入:
max2 = functools.partial(max,10)
实际上会把10作为*args的一部分自动加到左边,也就是:
max2(5, 6, 7)
相当于:
args = (10, 5, 6, 7)
max(*args)
结果为10。
小结
当函数的参数个数太多,需要简化时,使用functools.partial可以创建一个新的函数,这个新函数可以固定住原函数的部分参数,从而在调用时更简单。
二、Lambda
1,lambda的一般形式是关键字lambda后面跟一个或多个参数,紧跟一个冒号,以后是一个表达式。lambda是一个表达式而不是一个语句。它能够出现在Python语法不允许def出现的地方。作为表达式,lambda返回一个值(即一个新的函数)。lambda用来编写简单的函数,而def用来处理更强大的任务。
00001.
f =lambdax,y,z : x+y+z
printf(1,2,3)
g =lambdax,y=2,z=3: x+y+z
printg(1,z=4,y=5)
输出结果为:
6
10
2,lambda表达式常用来编写跳转表(jump table),就是行为的列表或字典。例如:
L = [(lambdax: x**2),
(lambdax: x**3),
(lambdax: x**4)]
printL[](2),L[1](2),L[2](2)
D = {'f1':(lambda:2+3),
'f2':(lambda:2*3),
'f3':(lambda:2**3)}
printD['f1'](),D['f2'](),D['f3']()
输出结果为:
4816
568
3,lambda表达式可以嵌套使用,但是从可读性的角度来说,应尽量避免使用嵌套的lambda表达式。
4,map函数可以在序列中映射函数进行操作。例如:
definc(x):
returnx+10
L = [1,2,3,4]
printmap(inc,L)
printmap((lambdax: x+10),L)
输出结果为:
[11,12,13,14]
[11,12,13,14]
5,列表解析可以实现map函数同样的功能,而且往往比map要快。例如:
print[x**2forxinrange(10)]
printmap((lambdax: x**2), range(10))
输出结果为:
[,1,4,9,16,25,36,49,64,81]
[,1,4,9,16,25,36,49,64,81]
6,列表解析比map更强大。例如:
print[x+yforxinrange(5)ifx%2==foryinrange(10)ify%2==1]输出结果为:
[1,3,5,7,9,3,5,7,9,11,5,7,9,11,13]
7,生成器函数就像一般的函数,但它们被用作实现迭代协议,因此生成器函数只能在迭代语境中出现。例如:
defgensquares(N):foriinrange(N):
yieldi**2
foriingensquares(5):
printi,
00001.
输出结果为:
14916
8,所有的迭代内容(包括for循环、map调用、列表解析等等)将会自动调用iter函数,来看看是不是支持了迭代协议。
9,生成器表达式就像列表解析一样,但它们是扩在圆括号()中而不是方括号[]中。例如:
fornumin(x**2forxinrange(5)):
printnum,
00001.
输出结果为:
14916
10,列表解析比for循环具有更好的性能。尽管如此,在编写Python代码时,性能不应该是最优先考虑的
11,没有return语句时,函数将返回None对象。
12,函数设计的概念:
·耦合性:只有在真正必要的情况下才使用全局变量
·耦合性:不要改变可变类型的参数,除非调用者希望这样做
·耦合性:避免直接改变另一个文件模块中的变量
·聚合性:每一个函数都应有一个单一的、统一的目标
13,最后给个默认参数和可变参数的例子:
defsaver(x=[]):
x.append(1)
printx
saver([2])
saver()
saver()
saver()
输出结果为:
[2,1]
[1]
[1,1]
[1,1,1]
三、python2.x与3.x中tkinter调用区别
python 2.x版本中import tkMessageBox
python3.X中变为import tkinter.messagebox
更改相应的import语句,Tkinter改成tkinter,然后
importtkMessageBox
改成
importtkinter.messagebox#对应着tkinter文件夹底下的messagebox.py
改成这种形式要注意接下来在引用的时候必须把import后边的符号全部写出来,否则出错:
messagebox.showinfo("title","hello world")#NameError: name 'messagebox' is not defined
或者改成
fromtkinterimportmessagebox#对应着tkinter文件夹底下的messagebox.py
则可以写成
messagebox.showinfo("title","hello world")
补充两点
1.packages可以认为是文件夹,而modules则可以看作是文件夹下的.py文件,而各色各样的import语句归结起来就是
from packages1.packages2 import modules1
或者
import packages1.packages2.modules1
2.
fromtkinterimport*
并不是将tkinter文件夹下的所有.py文件都import,实际上只是import了__init__.py中的所有对象,比如__init__.py中有个Tk对象,所以在使用了上面这条import语句后,可以直接引用Tk:
root = Tk()
但是如果想使用messagebox.py里的对象,还是得老老实实地引用它:
fromtkinterimportmessagebox#对应着tkinter文件夹底下的messagebox.py
Core Python Programming :路标偏函数GUI应用
# -*- coding: utf-8 -*-
"""
Created on Sat Jul 7 15:02:09 2018
@author: Administrator
"""
#! python3
from functools import partial as pto
from tkinter import *
from tkinter import Tk, Button, X,messagebox
WARN='warn'
CRIT='crit'
REGU='regu'
SIGNS={
'do not enter':CRIT,
'railroad crossig':WARN,
'55\nspeed limit':REGU,
'wrong way':CRIT,
'merging traffic':WARN,
'one way':REGU,
}
critCB=lambda: messagebox.showerror('Error','Error Button Pressed!')
warnCB=lambda: messagebox.showwarning('Warning','Warning Button Pressed!')
infoCB=lambda: messagebox.showinfo('Info','Info Button Pressed!')
top=Tk()
top.title('Road Signs')
Button(top,text='QUIT',command=top.quit,bg='red',fg='white').pack()
MyButton=pto(Button,top)
CritButton=pto(MyButton,command=critCB,bg='white',fg='red')
WarnButton=pto(MyButton,command=warnCB,bg='goldenrod1')
ReguButton=pto(MyButton,command=infoCB,bg='white')
for eachSign in SIGNS:
signType=SIGNS[eachSign]
cmd='%sButton(text=%r%s).pack(fill=X)'%(signType.title(),eachSign,'.upper()'if signType==CRIT else '.title()')
eval(cmd)
top.mainloop()
四、TensorFlow api更改
1、AttributeError:'module' object has no attribute 'SummaryWriter' tf.train.SummaryWriter改为:tf.summary.FileWriter
4、AttributeError:'module'object has no attribute'scalar_summary'tf.scalar_summary('images', images)改为:tf.summary.scalar('images', images) tf.image_summary('images', images)改为:tf.summary.image('images', images) ValueError: Only call `softmax_cross_entropy_with_logits` with named arguments (labels=..., logits=...,...) cifar10.loss(labels, logits) 改为:cifar10.loss(logits=logits, labels=labels) cross_entropy = tf.nn.softmax_cross_entropy_with_logits(logits, dense_labels, name='cross_entropy_per_example') 改为:cross_entropy = tf.nn.softmax_cross_entropy_with_logits(logits=logits, labels=dense_labels, name='cross_entropy_per_example')
5、ValueError: Shapes (2,128,1) and () are incompatible concated = tf.concat(1, [indices, sparse_labels])改为:concated = tf.concat([indices, sparse_labels],1)
6、重大API 变动:
1、TensorFlow models已经被移动到一个单独的github库。
2、除法和模运算符(/,//,%)现在匹配Python(flooring)语义。这也适用于 [tf.div] 和 [tf.mod]。要获取基于强制整数截断的行为,可以使用 [tf.truncatediv] 和 [tf.truncatemod]。
3、现在推荐使用[tf.divide()] 作为除法函数。[tf.div()] 将保留,但它的语义不会回应 Python3或[from future] 机制。
4、tf.reverse() 现在取轴的索引要反转。例如 [tf.reverse(a,[True,False,True])] 现在必须写为 [tf.reverse(a,[,2])]。 [tf.reverse_v2()] 将保持到TensorFlow1.0最终版。
5、[tf.mul,tf.sub ] 和 [tf.neg] 不再使用,改为 [tf.multiply],[tf.subtract] 和 [tf.negative]。
6、[tf.pack] 和 [tf.unpack] 弃用,改为 [tf.stack] 和 [tf.unstack]。7、[TensorArray.pack] 和 [TensorArray.unpack] 在弃用过程中,将来计划启用 [TensorArray.stack] 和 [TensorArray.unstack]。 以下Python函数的参数在引用特定域时,全部改为使用 [axis]。目前仍将保持旧的关键字参数的兼容性,但计划在1.0最终版完成前删除。
7、tf.listdiff已重命名为tf.setdiff1d以匹配NumPy命名。
8、tf.inv已被重命名为tf.reciprocal(组件的倒数),以避免与np.inv的混淆,后者是矩阵求逆。
9、tf.round现在使用banker的舍入(round to even)语义来匹配NumPy。4、tf.split现在以相反的顺序并使用不同的关键字接受参数。我们现在将NumPy order 匹配为tf.split(value,num_or_size_splits,axis)。
10、tf.sparse_split现在采用相反顺序的参数,并使用不同的关键字。我们现在将NumPy order 匹配为tf.sparse_split(sp_input,num_split,axis)。注意:我们暂时要求 tf.sparse_split 需要关键字参数。
11、tf.concat现在以相反的顺序并使用不同的关键字接受参数。特别地,我们现在将NumPy order匹配为tf.concat(values,axis,name)。
13、tf.complex_abs已从Python界面中删除。 tf.abs支持复杂张量,现在应该使用 tf.abs。
14、Template.var_scope属性重命名为.variable_scope
15、SyncReplicasOptimizer已删除,SyncReplicasOptimizerV2重命名为SyncReplicasOptimizer。
16、tf.zeros_initializer()和tf.ones_initializer()现在返回一个必须用initializer参数调用的可调用值,在代码中用tf.zeros_initializer()替换tf.zeros_initializer。
17、SparseTensor.shape已重命名为SparseTensor.dense_shape。与SparseTensorValue.shape相同。
19、使用tf.summary.FileWriter和tf.summary.FileWriterCache替换tf.train.SummaryWriter和tf.train.SummaryWriterCache。
20、从公共API中删除RegisterShape。使用C++形状函数注册。
21、Python API 中的 _ref dtypes 已经弃用。
22、在C++ API(intensorflow/cc)中,Input,Output等已经从tensorflow::ops命名空间移动到tensorflow。
23、将_cross_entropy_with_logits的arg order更改为(labels,predictions),并强制使用已命名的args。
领取专属 10元无门槛券
私享最新 技术干货