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

[经验分享] 【循序渐进学Python】6.Python中的函数

[复制链接]
发表于 2015-4-20 08:04:20 | 显示全部楼层 |阅读模式
1. 创建函数
  一个函数代表一个行为并且返回一个结果(包括None),在Python中使用def关键字来定义一个函数,如下:



def hello(name):
print 'hello,' + name + '!'
  接下来调用函数,并查看其返回值:



# output:
# hello,gy!
# None
print hello('gy')
  可以看到hello函数首先打印了:Hello,gy!,然后我们又将其返回值也打印出来,在这里因为没有返回具体的值,所以返回了None。
  
  下面我们可以定义一个用于计算斐波那契数列的函数,接收计算的位数(参数),返回计算的结果(返回值),如下:



1 def fibs(num):
2     result = [0,1]
3     for i in range(num - 2):
4         result.append(result[-2] + result[-1])
5     return result
6
7 # output: [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
8 print fibs(10)
  

2. 文档字符串
  文档字符串指的是在函数开头写下该函数的说明字符串,该字符串会作为函数的一部分进行存储。可以通过调用__doc__属性来查看:



1 def fibs(num):
2     "根据指位数来计算斐波那契数列"
3     result = [0,1]
4     for i in range(num - 2):
5         result.append(result[-2] + result[-1])
6     return result
7
8 # 输出:根据指位数来计算斐波那契数列
9 print fibs.__doc__
  

3. 参数
  函数使用参数来传递信息,而参数类型又基本分为两大类型:可变类型参考和不可变类型参数。
  

3.1 不可变类型参数
  不可变类型(字符串、数字和元组等)是不可变的,即无法修改,只能使用新的值来覆盖。使用不可变类型作为函数的参数时:在函数内为参数赋值不会改变其外部变量的值,如下:



1 # 字符串是不可变的
2 def try_to_change(n):
3     n = 'Gumby'
4
5 name = 'Sunshine'
6
7 # 尝试改变参数的值
8 try_to_change(name)
9
10 # output: Sunshine(函数内部的改变对其没有影响)
11 print name
  

3.2 可变类型参数
  可变类型参数(列表等)指的是:使用可变的数据结构来作为函数的参数使用。在函数内部修改可变类型参数的值时,会同时改变其外部变量的值(因为它们引用的其实是同一个对象),如下所示:



1 # 列表是可变的
2 def try_to_change2(n):
3     n[0] = 'Sunshine'
4
5 person = ['Gumby','Bob']
6 # 尝试改变参数的值
7 try_to_change2(person)
8
9 # output: ['Sunshine', 'Bob']
10 # 函数内部的改变会作用于外部的变量
11 print person
  
  如果想避免上面的情况可以对需要作为可变类型的参数的对象复制一个副本,这里是列表可以通过对其进行切片来返回一个新的副本,如下:



1 # 将可变的数据结构(列表)用作参数
2 def try_to_change2(n):
3     n[0] = 'Sunshine'
4
5 person = ['Gumby','Bob']
6 n = person[:] # 通过切片返回新的副本
7 try_to_change2(n)
8 print person # ['Gumby', 'Bob']
9 print n # ['Sunshine', 'Bob']
10 print n is person # False
  

3.3 关键字参数和默认值
  在我们之前使用参数的形式是:位置参数,即调用该函数给其传值时,是根据输入的值的先后顺序来给参数一一赋值 的。不过有时候如果我们需要定义的函数有大量的参数时,传值时只是于依赖于顺序的话是比较容易出错的。同时如果部分参数在不多数情况下值都是一样的,每次 调用都需要重新赋值也比较麻烦。针对于这种情况Python为我们提供了两个语法糖:即关键字参数默认值。(PS:C#4.0新增的两个特性:具名参数和可选参数,和Python的这两个语法糖很类似,感兴趣的同学可以参考这里:《Effective C#》读书笔记——条目10:使用可选参数减少方法重载的数量)。
  使用关键字参数不需要对函数进行任何修改,只需要在调用函数时显示为参数赋值即可(不依赖特定顺序),如下:



1 def hello(gretting,name):
2     print "%s,%s!" % (gretting,name)
3
4 # output: hello,world!
5 hello(name='world',gretting='hello')
  
  可以看到虽然调用时代码变多了,但是每个参数的含义一目了然。不过有时候我们的函数有些参数在大部分情况下使用同样的值,有时候也需要改变,这时候使用默认值,可以很好的解决这种问题,如下:



1 def hello(gretting = 'hello',name='world'):
2     print "%s,%s!" % (gretting,name)
3
4 hello() # hello,world!
5 hello(name = 'Sunshine') # hello,Sunshine!
6 hello('Greetings') # Greetings,world!
  可以看到,如果没有给任何值的话,函数自动使用默认值,也可以通过关键字参数指定部分值,其他的依然使用默认参数,这为我们的方法调用提供了很大的灵活性。
  

3.4 使用任意参数列表
  前面介绍的参数的个数基本都是固定的,有时候可以接收任意多的参数也是很有必要的,这时候可以使用Python为我们提供的语法糖(*号)来实现:



1 def print_params(number,*params):
2     print number
3     print params
4
5 # output:
6 # 6
7 # (1, 2, 3, 4, 5, 6)
8 print_params(6,1,2,3,4,5,6)
9
10 # output:
11 # 0
12 # ()
13 print_params(0)
  
  我们可以看到参数前的*号将所有的值放置到一个元组中(可以理解为将其他的参数收集起来)。如果没有为*号后的参数赋值则其值为一个空的元组。不过使用一个*号这样的语法不能处理关键字参数,如下:



1 def print_params(*params):
2     print params
3
4 # TypeError: print_params() got an unexpected keyword argument 'params'
5 print_params(params = (1,2,3))
  
  解决的办法很简单,使用**来修饰参数即可,如下所示:



1 # -- coding: utf-8 --
2 def print_params(**params):
3     print params
4     print type(params)
5
6 # output: {'params': (1, 2, 3)}
7 # output:
8 print_params(params = (1,2,3))
  可以看到使用**修饰的参数本质上其实是一个字典类型。可以通过这个字典来收集参数。
  

3.5 解包参数列表
  除了通过才定义函数的参数(形参)前添加*或者**来收集参数,我们还可以在调用函数时在实参前调解这两个操作符,它们表示其对应的逆过程。如下所示:



1 def add(x,y):
2     print x + y
3
4 params = (1,2)
5
6 # output: 3
7 add(*params)
  
  通过使用*操作符我们将params参数分割了add函数所需的两个参数,同样我们也可以使用**操作符来分割字典对象:



1 def hello(greeting,name):
2     print '%s,%s' %(greeting,name)
3
4 params = {'greeting':'hello','name':'world'}
5
6 # output: hello,world
7 # 这里使用*操作符也是可以的
8 hello(**params)
  

参考资料&进一步阅读
  Python基础教程(第二版)
  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-58609-1-1.html 上篇帖子: Python快速教程总结 下篇帖子: 使用python的unittest做测试
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

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

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

扫描微信二维码查看详情

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


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


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


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



合作伙伴: 青云cloud

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