自学Python二 Python中的屠龙刀(续)
函数
秉承着一切皆对象的理念,函数作为对象,可以为其赋值新的对象名,也可以作为参数传递给其他函数!
正常的诸如空函数,默认参数等等我们就不提了,在这里着重提一下默认参数里面的坑和lambda函数。
当默认参数为空list时的坑:定义一个函数,传入一个list,添加一个end后返回
>>> def func(l=[]):
... l.append('end')
... return l
...
>>>
正常调用是没什么问题的:
>>> func([1,2,3])
[1, 2, 3, 'end']
>>> func(['x','a','d'])
['x', 'a', 'd', 'end']
但是如果使用默认参数的话:
>>> func()
['end']
>>> func()
['end', 'end']
>>> func()
['end', 'end', 'end']
每次传入的都为上一个函数加了end之后的list,并不是一个空列表。原因是,函数定义之初,默认函数l已经开辟的空间为[],l是指向该list的变量,每次调用函数,传入的都为该l。所以如果改变了l的内容,下次调用时默认参数的内容也就变了,不是当初了[]
所以默认参数——>必须指向不可变对象!
下面让我们来优化下这个函数:
>>> def func(L=None):
... if L is None:
... L=[]
... L.append('End')
... return L
...
>>> func()
['End']
>>> func()
['End']
>>> func()
['End']
>>>
可变参数(传入的参数数目是可变的,可以是0个,1个2个多个):
假如我们要求:给定一组数字a,b,c...请计算a+b+c+...。由于参数不固定,一般的我们会传入一个list或者tuple。在python中我们可以这样定义函数:
>>> def func(*args):
... sum = 0
... for i in num:
... sum = sum + i
... return sum
...
>>> func(1,2,3,4,5)
15
其实所谓的可变参数就是这些参数在函数调用的时候自动组装成了一个tuple,本质上是一样的,但是用起来方便多了!
关键字参数(可变参数在函数调用时组装成了tuple,而关键字参数在函数调用时组装成了dict,当然你也可以直接传入一个dict):
>>> def func(name,age,**kw):
... print('name:',name, 'age:',age, 'other:',kw)
...
>>> func('Jack',39)
('name:', 'Jack', 'age:', 39, 'other:', {})
>>> func('Jack',39,gender='M',city='Bj')
('name:', 'Jack', 'age:', 39, 'other:', {'gender': 'M', 'city': 'Bj'})
在3.0+python中还可以限制关键字的名字,可以用命名关键字参数,例如只接收city作为关键字参数,则函数定义如下:
1 def person(name, age, *, city='Beijing', job):
2 print(name, age, city, job)
接下来就是我们的重头戏了!
匿名函数:
现在要求我们要定义一个函数,返回x+y的值。我们可以这样:
>>> def func(x,y):
... return x+y
...
>>> func(1,2)
3
>>> func = lambda x,y:x+y
>>> func(1,2)
3
lambda生成一个函数对象。
我们之前提到了,函数可以作为一个对象,作为参数传递或者作为结果输出。这是我们可以直接传入匿名函数:
>>> def test(f,a,b):
... print 'f is a function'
... print f(a,b)
...
>>> test((lambda x,y:x+y), 6, 9)
f is a function
15
上篇我们讲到了list,list的排序方法有list.sort(func=None,key=None,reverse=False)
>>> L = [('a',1),('c',3),('d',4),('b',2)]
>>> L.sort(lambda x,y:cmp(x[1],y[1]))#根据L中元素的第二个关键字排序
>>> L
[('a', 1), ('b', 2), ('c', 3), ('d', 4)]
还有Python中内置的一些高阶函数如map()函数,reduce()函数,他们当中也可以有匿名函数一席之地:
>>> map((lambda x:x*x),[1,2,3,4,5])#map函数,依次对list中每个元素进行处理
[1, 4, 9, 16, 25]
>>> map(str,[1,2,3])
['', '', '']
>>> reduce(lambda x,y:x*10+y,[1,4,8,3])#reduce函数,累进的将函数作用于list的每个元素。3.0中需要引入functools包
1483
闭包:
看下面这个例子:
>>> def line_conf():
... b = 15
... def line(x):
... return 2*x+b
... return line
...
>>> b = 5
>>> my_line = line_conf()
>>> print(my_line(5))
25
当一个函数跟它的环境变量合在一起,就构成了一个闭包,上面的例子中,函数line所需要的b的值是函数对象定义时提供的b值而不是使用时的b值。在python中,所谓的闭包就是一个包含有环境变量取值的函数对象,环境变量的取值被保存在函数对象的__closure__属性中!
1 >>> print(my_line.__closure__[0].cell_contents)
2 15
返回闭包时要牢记的一点:返回函数不要引用任何循环变量,或者后续会发生变化的变量。如下例所示:
>>> def count():
... fs = []
... for i in range(1,4):
... def f():
... return i * i
... fs.append(f)
... return fs
...
>>> f1,f2,f3 = count()
>>> f1()
9
>>> f2()
9
>>> f3()
9
我们本来想得到 f1() = 1, f2() = 4, f3() = 9。可是得到的结果全部为9.这是因为这几个函数都用到了循环变量i。当返回的时候i的值已经变成了3。现在我们把第一个例子修改一下:
>>> def line_conf():
... b = 15
... def line(x):
... return 2*x+b
... b = 100
... return line
...
>>> my_line = line_conf()
>>> print(my_line(5))
110
所以,再提一句:返回函数不要引用任何循环变量,或者后续会发生变化的变量!
如果一定要引用循环变量怎么办?方法是再创建一个函数,用该函数的参数绑定循环变量当前的值,无论循环变量后续如何更改,已绑定到函数的变量不变!
>>> def count():
... fs = []
... for i in range(1,4):
... def f(j):
... def g():
... return j*j
... return g
... fs.append(f(i))
... return fs
...
>>> f1,f2,f3 = count()
>>> f1()
1
>>> f2()
4
>>> f3()
9
未完待续
自学Python二 Python中的屠龙刀(续)的更多相关文章
- 自学Python一 迷茫中的开端!
有心学习一下Python,多门技术多条路啊.经历了找教程,看代码,写demo,这东西入门容易精通难啊!又因为请了两周婚假彻底忘光光.想了想自己还是边复习边写点什么东西吧.很多技术,新东西都是看了n多, ...
- python3.4学习笔记(二十二) python 在字符串里面插入指定分割符,将list中的字符转为数字
python3.4学习笔记(二十二) python 在字符串里面插入指定分割符,将list中的字符转为数字在字符串里面插入指定分割符的方法,先把字符串变成list然后用join方法变成字符串str=' ...
- 每天自学两小时Python,整理了最详细的学习路线和规
上次这篇文章每天自学两小时Python,三个月学通月入20K主要是给大家整理了学习资料视频和PDF书籍,很多需要的都关注私信领取了. 很多朋友领取之后都问我教程有了那么应该从哪去开始学习呢,私信太多我 ...
- [Python笔记]第十篇:模块续
requests Python标准库中提供了:urllib等模块以供Http请求,但是,它的 API 太渣了.它是为另一个时代.另一个互联网所创建的.它需要巨量的工作,甚至包括各种方法覆盖,来完成最简 ...
- Python基础---python中的异常处理
Python中的异常处理 一.什么是异常处理 python解释器检测到错误,触发异常(也允许程序员自己触发异常) 程序员编写特定的代码,专门用来捕捉这个异常(这段代码与程序逻辑无关,与异常处理有关) ...
- 用python在excel中读取与生成随机数写入excel中
今天是我第一次发博客,就关于python在excel中的应用作为我的第一篇吧. 具体要求是:在一份已知的excel表格中读取学生的学号与姓名,再将这些数据放到新的excel表中的第一列与第二列,最后再 ...
- 如何用Python在豆瓣中获取自己喜欢的TOP N电影信息
一.什么是 Python Python (蟒蛇)是一门简单易学. 优雅健壮. 功能强大. 面向对象的解释型脚本语言.具有 20+ 年发展历史, 成熟稳定. 具有丰富和强大的类库支持日常应用. 1989 ...
- 二十二. Python基础(22)--继承
二十二. Python基础(22)--继承 ● 知识框架 ● 继承关系中self的指向 当一个对象调用一个方法时,这个方法的self形参会指向这个对象 class A: def get(s ...
- python函数——形参中的:*args和**kwargs
python函数——形参中的:*args和**kwargs 多个实参,放到一个元组里面,以*开头,可以传多个参数:**是形参中按照关键字传值把多余的传值以字典的方式呈现 *args:(表示的就是将 ...
随机推荐
- VC 类泡泡龙游戏算法
#include <stdio.h> #include <malloc.h> #include <string.h> /* 1 2 1 2 2 1 2 1 2 1 ...
- android 开发进阶自定义控件 类似 TextView
开发自定义控件的步骤: 1. 继承View: 2.重写构造函数并构造方法中获得我们自定义的属性. 3. 重写onDraw, 4.重写onMeasure 等函数 一.自定义View的属性,首先在res/ ...
- 008 The Generics In JAVA
泛型是JAVA的核心特型之一,我们先看一个例子: 没有使用泛型前,如下: import java.util.ArrayList; import java.util.List; public class ...
- SQL必知必会笔记(1)
去SQL AXDB 中Query数据 Open the SQL > Connect > Select AXDB > new Query select REFID, ITEMID, R ...
- Android开发-API指南-进程与线程
Processes and Threads 英文原文:http://developer.android.com/guide/components/processes-and-threads.html ...
- Android7.0 拨号盘应用源码分析(一) 界面浅析
前言 android拨号盘的源码目录在package/app/Dialer 自7.0以后Incallui的源码直接放到了Dialer目录下,虽然在7.0以前incallui有自己独立的目录,但实际编译 ...
- NOI2002 银河英雄传说
P1196 银河英雄传说 367通过 1.1K提交 题目提供者该用户不存在 标签并查集NOI系列2001(或之前) 难度提高+/省选- 提交该题 讨论 题解 记录 最新讨论 莱因哈特什么鬼? 私人代码 ...
- ios assetlibrary
公司做个app项目,用phonegap做,好调页面,哎,就是骗那些土大款客户,觉得phonegap性能一般吧,不过html5的确好强大,页面设计好了看起来也好看.原生的用的不多,比如什么二维码扫描啊, ...
- extern “C”调用测试与验证-2016.01.06
1 调用情形说明 在上一篇关于extern “c”原理以及用法中,详细的说明了为什么需要extern “c”以及如何使用它解决c与c++混合编程时遇到的问题.接下来,使用示例验证方式验证c与c++函数 ...
- kbengine mmo源码(完整服务端源码+资源+完整客户端源码)
本项目作为kbengine服务端引擎的客户端演示而写 更新kbengine插件库(https://github.com/kbengine/kbengine_unity3d_plugins): ...