这里我们看看Python中函数定义的语法,函数的局部变量,函数的参数,Python中函数的形参可以有默认值,参数的传递是赋值操作,在函数调用时,可以对实参进行打包和解包

 1,函数定义

关键字def引出函数定义,后面跟着函数名以及用括号括起来的一系列参数,然后从下一行开始函数体(function body),并且要缩进。

生成一个Fibnacci数列的序列,最大不超过某个数的函数

 def fib(n):
'''get a list of fibnacci series to n'''
a, b = 0, 1
result = []
while a<n:
result.append(a)
a, b = b, a+b
return result

运行:

>>> fib(3000)
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584]

2,函数的局部变量

[这里的符号表(symbol table)等同于命名空间(namespace)]

函数体的执行会为这个函数的局部变量引入一个新的符号表(symbol table)。所有函数体中的赋值语句(assignment statement),都会把变量名和值存在这个符号表中。

而函数体中的引用一个变量时,首先查看函数的符号表,如果这个函数定义包裹在其它函数定义中,就依次查看外围函数的符号表,然后查看全局符号表(也就是函数所属的module的符号表),最后查看Python的内置类型和变量的符号表。

函数的行参也是存在于函数的局部符号表中。

一个例子,函数中引用的是在局部符号表中的参数l,而不是全局符号表中的l。

 l = ['a', 'b']    #输出[1,2]
def f(l):
print l
if __name__ == "__main__":
f([1,2])

函数调用的实参传递是通过赋值语句做的,所以传递的是object的引用,对于序列这样的可变类型(mutable),按引用传递的话,如果序列做参数在函数体中改变它的值也会影响它在外围符号表的值,这就像C++中的引用

 l = ['a', 'b']
def f(l):
l.append("")
if __name__ == "__main__":
f(l)
print l

输出结果是:

['a', 'b', '22']

3,函数的默认参数

3.1  基础

函数可以有默认参数,有默认值的参数必须在没有默认值的参数后面

 def f(a, b=5, c="hello"):
print c, a+b
if __name__ == "__main__":
f(3)
f(3, 4, "hi")

函数参数的默认值如果取自一个变量,那这个默认值会在函数定义的地方被计算得到,默认值只会被计算一次

 i = 6
def f(n=i):
print n
i = 7

会输出6

3.2当参数的默认值是list这样的可变对象(mutable object)

函数的默认参数只会被计算一次,不管函数被怎么调用,所以当参数是list这样的可变对象时,但在函数体中其值被改变时,再次调用参数的默认值就是改变后的值

 def f(n, l=[]):
l.append(n)
print l
if __name__ == "__main__":
f(1)
f(2)
f(3)

猜猜看会输出什么?输出

[1]
[1, 2]
[1, 2, 3]

也就是从f(2)调用开始,l的默认值就变了,不会再重新计算一次默认值了。

怎么避免这样的情况呢?用下面的代码

 def f(n, l=None):
if l is None:
l = []
l.append(n)
print l
if __name__ == "__main__":
f(1)
f(2)
f(3)

输出结果:

[1]
[2]
[3]

None是个内置常量,当然不能被改变,每次f被调用就会用这个值给l赋值

[问题?]这里其实我有个待弄明白的问题,默认值是只会被计算一次还是参数只会被初始化一次,也就是符号表是每次函数调用都建立和销毁,还是函数生存期一直存在,所用调用共用一个。

[答案]现在有答案了,函数的符号表,也就是其局部命名空间会在每次调用和返回时进行创建初始化和删除。

4,关键字实参(keyword argument)

实参(argument)是指函数调用时传递进去的参数值(value),区别于形参(parameter)。

Python实参(argument)分为两类,关键字实参和位置实参(positional argument)。

关键字实参就是在调用函数的时候,以name=value的形式传递参数,name就是参数定义的名字,也就是形参;关键字参数指明了参数名,所以可以不用管其调用时候顺序。

位置实参就是只传递value的形式,顾名思义,这要靠实参的位置来匹配形参,关键字参数必须位于位置参数之后 。

举一个简单的例子

 def f(a, b, c):
print "a =", a, "b =", b, "c =", c
if __name__ == "__main__":
f(5, c=8, b=2)

输出结果:

a = 5 b = 2 c = 8

5,参数的解包(unpacking)

如果我们有一个list或一个dict,可把它直接作为参数传给一个函数,里面的值可以解包出来传给一个个参数。

5.1 解包为位置实参

可以把一个list或tuple解包,对应的值作为位置参数传递,调用的时候要以*args的形式

>>> range(2,5)
[2, 3, 4]
>>> args=[2,5]
>>> range(*args) #注意调用语法“*args"
[2, 3, 4]

range接受两个参数,给它传入一个tuple[2,5],解包。

5.2 解包为关键字实参

要解包为关键字参数,使用字典。字典的key为形参的name,是字符串,字典value为传递的实参。

语法上在调用的时候以**args的形式

使用4小节的例子,输出结果相同

 def f(a, b, c):
print "a =", a, "b =", b, "c =", c
if __name__ == "__main__":
d = {"a":5, "c":8, "b":2}
f(**d) #注意调用语法“**args"

6,参数的打包,传递任意个参数(packing)

可不可以给函数传递任意个参数呢,可以的,多余的实参可以被打包成一个元组(tuple),传给一个形参。

这个行参在定义时前面加上“*”,即*args

一个小例子,把实参打包成tuple输出

 def multiple_argu(*args):
print args
if __name__ == "__main__":
multiple_argu('a', 'b', 'c', 'd')

输出了一个tuple:

('a', 'b', 'c', 'd')

参考:

http://docs.python.org/3/glossary.html#term-argument  Python文档,术语

http://docs.python.org/2.7/tutorial/controlflow.html#defining-functions  Python文档

Python基础-函数(function)的更多相关文章

  1. python基础—函数嵌套与闭包

    python基础-函数嵌套与闭包 1.名称空间与作用域 1 名称空间分为: 1 内置名称空间   内置在解释器中的名称 2 全局名称空间   顶头写的名称 3 局部名称空间 2 找一个名称的查找顺序: ...

  2. python基础—函数装饰器

    python基础-函数装饰器 1.什么是装饰器 装饰器本质上是一个python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能. 装饰器的返回值是也是一个函数对象. 装饰器经常用于有切 ...

  3. Python基础-函数参数

    Python基础-函数参数 写在前面 如非特别说明,下文均基于Python3 摘要 本文详细介绍了函数的各种形参类型,包括位置参数,默认参数值,关键字参数,任意参数列表,强制关键字参数:也介绍了调用函 ...

  4. python基础,函数,面向对象,模块练习

    ---恢复内容开始--- python基础,函数,面向对象,模块练习 1,简述python中基本数据类型中表示False的数据有哪些? #  [] {} () None 0 2,位和字节的关系? # ...

  5. python基础——函数的参数

    python基础——函数的参数 定义函数的时候,我们把参数的名字和位置确定下来,函数的接口定义就完成了.对于函数的调用者来说,只需要知道如何传递正确的参数,以及函数将返回什么样的值就够了,函数内部的复 ...

  6. Python基础-函数篇

    本节内容 1. 函数基本语法及特性 2. 参数与局部变量 3. 返回值 嵌套函数 4.递归 5.匿名函数 6.函数式编程介绍 7.高阶函数 8.内置函数  函数与函数式编程 1.面向对象: 华山派-- ...

  7. 第三章:Python基础の函数和文件操作实战

    本課主題 Set 集合和操作实战 函数介紹和操作实战 参数的深入介绍和操作实战 format 函数操作实战 lambda 表达式介绍 文件操作函数介紹和操作实战 本周作业 Set 集合和操作实战 Se ...

  8. python基础-函数基本特性和用法

    函数: 初中数学函数定义:一般的,在一个变化过程中,如果有两个变量x和y,并且对于x的每一个确定的值,y都有唯一确定的值与其对应,那么我们就把x称为自变量,把y称为因变量,y是x的函数.自变量x的取值 ...

  9. python基础——函数

    1.内置函数的调用: 可以在官方网站查找内置函数及说明,也可以通过help(abs)函数查看相应的信息. https://docs.python.org/3/library/functions.htm ...

  10. Python基础(函数,函数的定义,函数的调用,函数的参数,递归函数)

    1.函数 我们知道圆的面积计算公式为: S = πr2 当我们知道半径r的值时,就可以根据公式计算出面积.假设我们需要计算3个不同大小的圆的面积: r1 = 12.34 r2 = 9.08 r3 = ...

随机推荐

  1. c#快捷键大全

    转发:http://zhidao.baidu.com/question/444655283 直接贴出来吧(关于VS的): 快捷键 功能 CTRL + SHIFT + B生成解决方案 CTRL + F7 ...

  2. HDU 3863 (博弈) No Gambling

    这是我见过的最简单的一道博弈了,其实不要被复杂的棋盘吓到了. 首先肯定会有而且仅有一个人胜,而且因为棋盘是对称的,所以先手相对于后手肯定更有优势,那么肯定是先手赢. 这是不是严格的推理,但是确实比较容 ...

  3. CI在CentOS中的部署与实践LNMP

    1. 平台:lnmp CentOS6.4 (64bit) nginx1.2.4+php5.5.7配置过程中遇到的问题与处理方式: 1. 404错误: 原因:nginx中的配置请求路径的问题 2. 40 ...

  4. Spring3.1中使用profile配置开发测试线上环境

    如果在开发时进行一些数据库测试,希望链接到一个测试的数据库,以避免对开发数据库的影响. 开发时的某些配置比如log4j日志的级别,和生产环境又有所区别. 各种此类的需求,让我希望有一个简单的切换开发环 ...

  5. Activity传递对象的方法

    //Serializeable传递对象的方法 public void SerializeMethod(){ Person mPerson = new Person(); mPerson.setName ...

  6. UESTC 1854

    题目意思  就是说 有一个起点一个终点  和一些虫洞,从一个虫洞进去然后出来,是不需要消耗时间的,注意点就是,虫洞是一条线段,你可以从线段的任意位置进去,从任意位置出来: 所以从一个虫洞到另一个虫洞的 ...

  7. Windows 8 电话激活密钥。(更新至 2013-07-21)

    MAK密钥,可用于电话激活专业版&企业版,2013.7.21 更新,共22枚: slmgr.vbs -ipk MQJNQ-G2TKM-YJP7W-CCXVY-VQR92slmgr.vbs -i ...

  8. 响应式设计中几个class区别

    table-responsive:在小屏幕时不对内容做任何额外排版,只是允许左右滑动 scrollable-area:先尝试挤压起来,实在不行再左右滑动

  9. div 绝对布局居中

    #loginbg{ position:absolute; height:200px; width:400px; margin:-100px 0px 0px -200px; top: 50%; left ...

  10. 可接受多个值的文件上传字段HTML5新特性

    <input type="file" id="input"  multiple="multiple"> 主要是多了个multip ...