函数

  秉承着一切皆对象的理念,函数作为对象,可以为其赋值新的对象名,也可以作为参数传递给其他函数!

  正常的诸如空函数,默认参数等等我们就不提了,在这里着重提一下默认参数里面的坑和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中的屠龙刀(续)的更多相关文章

  1. 自学Python一 迷茫中的开端!

    有心学习一下Python,多门技术多条路啊.经历了找教程,看代码,写demo,这东西入门容易精通难啊!又因为请了两周婚假彻底忘光光.想了想自己还是边复习边写点什么东西吧.很多技术,新东西都是看了n多, ...

  2. python3.4学习笔记(二十二) python 在字符串里面插入指定分割符,将list中的字符转为数字

    python3.4学习笔记(二十二) python 在字符串里面插入指定分割符,将list中的字符转为数字在字符串里面插入指定分割符的方法,先把字符串变成list然后用join方法变成字符串str=' ...

  3. 每天自学两小时Python,整理了最详细的学习路线和规

    上次这篇文章每天自学两小时Python,三个月学通月入20K主要是给大家整理了学习资料视频和PDF书籍,很多需要的都关注私信领取了. 很多朋友领取之后都问我教程有了那么应该从哪去开始学习呢,私信太多我 ...

  4. [Python笔记]第十篇:模块续

    requests Python标准库中提供了:urllib等模块以供Http请求,但是,它的 API 太渣了.它是为另一个时代.另一个互联网所创建的.它需要巨量的工作,甚至包括各种方法覆盖,来完成最简 ...

  5. Python基础---python中的异常处理

    Python中的异常处理 一.什么是异常处理 python解释器检测到错误,触发异常(也允许程序员自己触发异常) 程序员编写特定的代码,专门用来捕捉这个异常(这段代码与程序逻辑无关,与异常处理有关) ...

  6. 用python在excel中读取与生成随机数写入excel中

    今天是我第一次发博客,就关于python在excel中的应用作为我的第一篇吧. 具体要求是:在一份已知的excel表格中读取学生的学号与姓名,再将这些数据放到新的excel表中的第一列与第二列,最后再 ...

  7. 如何用Python在豆瓣中获取自己喜欢的TOP N电影信息

    一.什么是 Python Python (蟒蛇)是一门简单易学. 优雅健壮. 功能强大. 面向对象的解释型脚本语言.具有 20+ 年发展历史, 成熟稳定. 具有丰富和强大的类库支持日常应用. 1989 ...

  8. 二十二. Python基础(22)--继承

    二十二. Python基础(22)--继承 ● 知识框架   ● 继承关系中self的指向 当一个对象调用一个方法时,这个方法的self形参会指向这个对象 class A:     def get(s ...

  9. python函数——形参中的:*args和**kwargs

    python函数——形参中的:*args和**kwargs   多个实参,放到一个元组里面,以*开头,可以传多个参数:**是形参中按照关键字传值把多余的传值以字典的方式呈现 *args:(表示的就是将 ...

随机推荐

  1. [转]SVN-版本控制软件

    一.版本控制软件 1.为什么需要版本控制软件 问题:① 团队开发 ② 异地协作 ③ 版本回退 2.解决之道 SCM(Software Configuration Management):软件配置管理 ...

  2. 【Unity Shaders】学习笔记——渲染管线

    [Unity Shaders]学习笔记——Shader和渲染管线 转载请注明出处:http://www.cnblogs.com/-867259206/p/5595924.html 写作本系列文章时使用 ...

  3. Xcode 中 Git 的配置与使用

    Xcode 中 Git 的配置与使用主要围绕下面几个问题展开阐述: 问题1,如何在Xcode中创建本地代码库,并添加和提交代码到本地代码库? 问题2,如何在Xcode中提交推送给远程服务器代码库? 问 ...

  4. jQuery 的随机密码生成 .

    $.extend({ password: function (length, special) { var iteration = 0; var password = ""; va ...

  5. ZJOI2009 假期的宿舍

    题目描述 学校放假了 · · · · · · 有些同学回家了,而有些同学则有以前的好朋友来探访,那么住宿就是一个问题.比如 A 和 B 都是学校的学生,A 要回家,而 C 来看B,C 与 A 不认识. ...

  6. Android四大组件小结

    Android四大组件分别为activity.service.content provider.broadcast receiver. 一.android四大组件详解 1.activity (1)一个 ...

  7. 开源项目:网页实时通信WebRTC

    参考资料 [博客系列] Android WebRTC 音视频开发总结 [环境编译] WebRTC入门指南 各平台WebRTC源码网盘下载 Ubuntu14.04编译WebRTC For Android ...

  8. 如何利用jq来实现复选框的全选,反选!

    $("document").ready(function(){ $("#btn1").click(function(){ $("[name='chec ...

  9. xdotool-linux下的按键精灵

    这是我在ST写的用来自动打开机顶盒的脚本 #!/bin/bash init_stb() { xdotool type "telnet 10.80.117.$1" xdotool k ...

  10. 一、Struts2的概述

    一.Struts2概述 是什么? Struts2是一个M(模型---域--范围模型)V(View视图)C(控制器)框架(模型2).框架都是一个半成品.提高开发效率. Struts1是一个MVC框架,非 ...