设为首页 收藏本站
查看: 762|回复: 0

[经验分享] Python基础-函数(function)

[复制链接]

尚未签到

发表于 2015-4-26 07:33:31 | 显示全部楼层 |阅读模式
  这里我们看看Python中函数定义的语法,函数的局部变量,函数的参数,Python中函数的形参可以有默认值,参数的传递是赋值操作,在函数调用时,可以对实参进行打包和解包
  
   1,函数定义
  关键字def引出函数定义,后面跟着函数名以及用括号括起来的一系列参数,然后从下一行开始函数体(function body),并且要缩进。
  生成一个Fibnacci数列的序列,最大不超过某个数的函数



1 def fib(n):
2     '''get a list of fibnacci series to n'''
3     a, b = 0, 1
4     result = []
5     while a>> 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。



1 l = ['a', 'b']    #输出[1,2]
2 def f(l):
3     print l
4 if __name__ == "__main__":
5     f([1,2])
  
  函数调用的实参传递是通过赋值语句做的,所以传递的是object的引用,对于序列这样的可变类型(mutable),按引用传递的话,如果序列做参数在函数体中改变它的值也会影响它在外围符号表的值,这就像C++中的引用



1 l = ['a', 'b']
2 def f(l):
3     l.append("22")
4 if __name__ == "__main__":
5     f(l)
6     print l
  输出结果是:
  ['a', 'b', '22']
  
  3,函数的默认参数
  3.1  基础
  函数可以有默认参数,有默认值的参数必须在没有默认值的参数后面



1 def f(a, b=5, c="hello"):
2     print c, a+b
3 if __name__ == "__main__":
4     f(3)
5     f(3, 4, "hi")
  
  函数参数的默认值如果取自一个变量,那这个默认值会在函数定义的地方被计算得到,默认值只会被计算一次



1 i = 6
2 def f(n=i):
3     print n
4 i = 7
  会输出6
  
  3.2当参数的默认值是list这样的可变对象(mutable object)
  函数的默认参数只会被计算一次,不管函数被怎么调用,所以当参数是list这样的可变对象时,但在函数体中其值被改变时,再次调用参数的默认值就是改变后的值



1 def f(n, l=[]):
2     l.append(n)
3     print l
4 if __name__ == "__main__":
5     f(1)
6     f(2)
7     f(3)
  猜猜看会输出什么?输出
  [1]
[1, 2]
[1, 2, 3]
  也就是从f(2)调用开始,l的默认值就变了,不会再重新计算一次默认值了。
  怎么避免这样的情况呢?用下面的代码



1 def f(n, l=None):
2     if l is None:
3         l = []
4     l.append(n)
5     print l
6 if __name__ == "__main__":
7     f(1)
8     f(2)
9     f(3)
  输出结果:
  [1]
[2]
[3]
  None是个内置常量,当然不能被改变,每次f被调用就会用这个值给l赋值
  
  [问题?]这里其实我有个待弄明白的问题,默认值是只会被计算一次还是参数只会被初始化一次,也就是符号表是每次函数调用都建立和销毁,还是函数生存期一直存在,所用调用共用一个。
  [答案]现在有答案了,函数的符号表,也就是其局部命名空间会在每次调用和返回时进行创建初始化和删除。
  
  
  4,关键字实参(keyword argument)
  实参(argument)是指函数调用时传递进去的参数值(value),区别于形参(parameter)。
  Python实参(argument)分为两类,关键字实参和位置实参(positional argument)。
  关键字实参就是在调用函数的时候,以name=value的形式传递参数,name就是参数定义的名字,也就是形参;关键字参数指明了参数名,所以可以不用管其调用时候顺序。
  位置实参就是只传递value的形式,顾名思义,这要靠实参的位置来匹配形参,关键字参数必须位于位置参数之后 。
  举一个简单的例子



1 def f(a, b, c):
2     print "a =", a, "b =", b, "c =", c
3 if __name__ == "__main__":
4     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小节的例子,输出结果相同



1 def f(a, b, c):
2     print "a =", a, "b =", b, "c =", c
3 if __name__ == "__main__":
4     d = {"a":5, "c":8, "b":2}
5     f(**d)      #注意调用语法“**args"
  
  
  6,参数的打包,传递任意个参数(packing)
  可不可以给函数传递任意个参数呢,可以的,多余的实参可以被打包成一个元组(tuple),传给一个形参。
  这个行参在定义时前面加上“*”,即*args
  一个小例子,把实参打包成tuple输出



1 def multiple_argu(*args):
2     print args
3 if __name__ == "__main__":
4     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文档
  

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-60687-1-1.html 上篇帖子: 让你的IIS执行Python脚本,并推荐一个Python的MVC框架 下篇帖子: Python学习笔记十(pymssql数据库操作)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表