这里我们看看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. 漫游Kafka实现篇之消息和日志

    消息格式 消息由一个固定长度的头部和可变长度的字节数组组成.头部包含了一个版本号和CRC32校验码. /** * 具有N个字节的消息的格式如下 * * 如果版本号是0 * * 1. 1个字节的 &qu ...

  2. 漫游Kafka实战篇之客户端API

    Kafka Producer APIs 旧版的Procuder API有两种:kafka.producer.SyncProducer和kafka.producer.async.AsyncProduce ...

  3. 菜鸟学习笔记4——jquery事件

    方法 描述 bind() 向匹配元素附加一个或更多事件处理器 blur() 触发.或将函数绑定到指定元素的 blur 事件 change() 触发.或将函数绑定到指定元素的 change 事件 cli ...

  4. GrepCode

    /***************************************************************************** * GrepCode * 声明: * 最近 ...

  5. android中handler用法总结

    一.Handler的定义: Handler主要接收子线程发送的数据, 并用此数据配合主线程更新UI,用来跟UI主线程交互用.比如可以用handler发送一个message,然后在handler的线程中 ...

  6. 关于微信扫描二维码下载apk文件的细节设计

    微信使用的人数越来越多,渐渐的用户形成了一种习惯,扫描二维码的时候,也会打开微信去扫描,但是微信不支持第三方的链接下载,有些厂商已经发现了这一特点,所以在使用二维码下载自家的app时,会做一个提示,引 ...

  7. MySQL与Oracle 差异比较之七其它

    其它 编号 类别 ORACLE MYSQL 注释 1 内连接的更改 1.select a.*, b.*, c.*, d.*  from a, b, c, d where a.id = b.id   a ...

  8. bsp tree

    http://www.cnblogs.com/dreams/archive/2007/03/25/687267.html http://blog.csdn.net/iduosi/article/det ...

  9. ajax url参数中文乱码解决

    1.较好的处理办法,对js的url中的中文参数值使用两次encodeURI(),即 encodeURI(encodeURI("url的中文参数值")), java代码中使用URLD ...

  10. HDU5808Price List Strike Back (BestCoder Round #86 E) cdq分治+背包

    严格按题解写,看能不能形成sum,只需要分割当前sum怎么由两边组成就好 #include <cstdio> #include <cstring> #include <c ...