这里我们看看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. HDU5400 Arithmetic Sequence

    解题思路:这题看懂题目是很关键的,这个区间是等差数列,且公差为d1或d2, 特别注意单个数字也为等差数列.每次求出等差数列序列长度,然后   求出对应这种长度对应有多少种组合方式,累加起来就是结果. ...

  2. HDU5427

    #include<cstdio> #include<iostream> #include<cstring> #include<algorithm> us ...

  3. 湖大 11404 manacher

    链接   http://acm.hunnu.edu.cn/online/?action=problem&type=show&id=11404&courseid=0 求 最长回文 ...

  4. 射手网字幕打包下载(73.16G)

    射手网陪着我度过15年了. 我所希望射手网所具有的价值,就是能令更多人跨越国家的樊篱,了解世界上不同的文化. 如果这个网站有帮到人,我就已经很满足了. 但是,需要射手网的时代已经走开了. 因此,今天, ...

  5. 剑指offer—第三章高质量的代码(按顺序打印从1到n位十进制数)

    题目:输入一个数字n,按照顺序打印出1到最大n位十进制数,比如输入3,则打印出1,2,3直到最大的3位数999为止. 本题陷阱:没有考虑到大数的问题. 本题解题思路:将要打印的数字,看成字符串,不足位 ...

  6. 嵌入式 Linux下curl库API简单介绍

    1:CURLcode curl_global_init(long flags); 这个函数全局需要调用一次(多次调用也可以,不过没有必要), 所以这也是把Curlplus设计成单体类的原因,curl_ ...

  7. Unicode和汉字编码小知识

    Unicode和汉字编码小知识 将汉字进行UNICODE编码,如:“王”编码后就成了“\王”,UNICODE字符以\u开始,后面有4个数字或者字母,所有字符都是16进制的数字,每两位表示的256以内的 ...

  8. JDBC数据源(DataSource)的简单实现

    数据源技术是Java操作数据库的一个很关键技术,流行的持久化框架都离不开数据源的应用.   数据源提供了一种简单获取数据库连接的方式,并能在内部通过一个池的机制来复用数据库连接,这样就大大减少创建数据 ...

  9. php获取网站根目录

    php获取网站根目录方法一:<?phpdefine("WWWROOT",str_ireplace(str_replace("/","\\&quo ...

  10. Linux基本命令(10)其他命令

    其他命令 命令 功能 命令 功能 echo 显示一字串 passwd 修改密码 clear 清除显示器 lpr 打印 lpq 查看在打印队列中等待的作业 lprm 取消打印队列中的作业 10.1 ec ...