【循序渐进学Python】6.Python中的函数
1. 创建函数
一个函数代表一个行为并且返回一个结果(包括None),在Python中使用def关键字来定义一个函数,如下:
def hello(name):
print 'hello,' + name + '!'
接下来调用函数,并查看其返回值:
# output:
# hello,gy!
# None
print hello('gy')
可以看到hello函数首先打印了:Hello,gy!,然后我们又将其返回值也打印出来,在这里因为没有返回具体的值,所以返回了None。
下面我们可以定义一个用于计算斐波那契数列的函数,接收计算的位数(参数),返回计算的结果(返回值),如下:
def fibs(num):
result = [0,1]
for i in range(num - 2):
result.append(result[-2] + result[-1])
return result # output: [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
print fibs(10)
2. 文档字符串
文档字符串指的是在函数开头写下该函数的说明字符串,该字符串会作为函数的一部分进行存储。可以通过调用__doc__属性来查看:
def fibs(num):
"根据指位数来计算斐波那契数列"
result = [0,1]
for i in range(num - 2):
result.append(result[-2] + result[-1])
return result # 输出:根据指位数来计算斐波那契数列
print fibs.__doc__
3. 参数
函数使用参数来传递信息,而参数类型又基本分为两大类型:可变类型参考和不可变类型参数。
3.1 不可变类型参数
不可变类型(字符串、数字和元组等)是不可变的,即无法修改,只能使用新的值来覆盖。使用不可变类型作为函数的参数时:在函数内为参数赋值不会改变其外部变量的值,如下:
# 字符串是不可变的
def try_to_change(n):
n = 'Gumby' name = 'Sunshine' # 尝试改变参数的值
try_to_change(name) # output: Sunshine(函数内部的改变对其没有影响)
print name
3.2 可变类型参数
可变类型参数(列表等)指的是:使用可变的数据结构来作为函数的参数使用。在函数内部修改可变类型参数的值时,会同时改变其外部变量的值(因为它们引用的其实是同一个对象),如下所示:
# 列表是可变的
def try_to_change2(n):
n[0] = 'Sunshine' person = ['Gumby','Bob']
# 尝试改变参数的值
try_to_change2(person) # output: ['Sunshine', 'Bob']
# 函数内部的改变会作用于外部的变量
print person
如果想避免上面的情况可以对需要作为可变类型的参数的对象复制一个副本,这里是列表可以通过对其进行切片来返回一个新的副本,如下:
# 将可变的数据结构(列表)用作参数
def try_to_change2(n):
n[0] = 'Sunshine' person = ['Gumby','Bob']
n = person[:] # 通过切片返回新的副本
try_to_change2(n)
print person # ['Gumby', 'Bob']
print n # ['Sunshine', 'Bob']
print n is person # False
3.3 关键字参数和默认值
在我们之前使用参数的形式是:位置参数,即调用该函数给其传值时,是根据输入的值的先后顺序来给参数一一赋值 的。不过有时候如果我们需要定义的函数有大量的参数时,传值时只是于依赖于顺序的话是比较容易出错的。同时如果部分参数在不多数情况下值都是一样的,每次 调用都需要重新赋值也比较麻烦。针对于这种情况Python为我们提供了两个语法糖:即关键字参数和默认值。(PS:C#4.0新增的两个特性:具名参数和可选参数,和Python的这两个语法糖很类似,感兴趣的同学可以参考这里:《Effective C#》读书笔记——条目10:使用可选参数减少方法重载的数量<C#语言习惯>)。
使用关键字参数不需要对函数进行任何修改,只需要在调用函数时显示为参数赋值即可(不依赖特定顺序),如下:
def hello(gretting,name):
print "%s,%s!" % (gretting,name) # output: hello,world!
hello(name='world',gretting='hello')
可以看到虽然调用时代码变多了,但是每个参数的含义一目了然。不过有时候我们的函数有些参数在大部分情况下使用同样的值,有时候也需要改变,这时候使用默认值,可以很好的解决这种问题,如下:
def hello(gretting = 'hello',name='world'):
print "%s,%s!" % (gretting,name) hello() # hello,world!
hello(name = 'Sunshine') # hello,Sunshine!
hello('Greetings') # Greetings,world!
可以看到,如果没有给任何值的话,函数自动使用默认值,也可以通过关键字参数指定部分值,其他的依然使用默认参数,这为我们的方法调用提供了很大的灵活性。
3.4 使用任意参数列表
前面介绍的参数的个数基本都是固定的,有时候可以接收任意多的参数也是很有必要的,这时候可以使用Python为我们提供的语法糖(*号)来实现:
def print_params(number,*params):
print number
print params # output:
#
# (1, 2, 3, 4, 5, 6)
print_params(6,1,2,3,4,5,6) # output:
#
# ()
print_params(0)
我们可以看到参数前的*号将所有的值放置到一个元组中(可以理解为将其他的参数收集起来)。如果没有为*号后的参数赋值则其值为一个空的元组。不过使用一个*号这样的语法不能处理关键字参数,如下:
def print_params(*params):
print params # TypeError: print_params() got an unexpected keyword argument 'params'
print_params(params = (1,2,3))
解决的办法很简单,使用**来修饰参数即可,如下所示:
# -- coding: utf-8 --
def print_params(**params):
print params
print type(params) # output: {'params': (1, 2, 3)}
# output: <type 'dict'>
print_params(params = (1,2,3))
可以看到使用**修饰的参数本质上其实是一个字典类型。可以通过这个字典来收集参数。
3.5 解包参数列表
除了通过才定义函数的参数(形参)前添加*或者**来收集参数,我们还可以在调用函数时在实参前调解这两个操作符,它们表示其对应的逆过程。如下所示:
def add(x,y):
print x + y params = (1,2) # output: 3
add(*params)
通过使用*操作符我们将params参数分割了add函数所需的两个参数,同样我们也可以使用**操作符来分割字典对象:
def hello(greeting,name):
print '%s,%s' %(greeting,name) params = {'greeting':'hello','name':'world'} # output: hello,world
# 这里使用*操作符也是可以的
hello(**params)
参考资料&进一步阅读
【循序渐进学Python】6.Python中的函数的更多相关文章
- python开发_python中的函数定义
下面是我做的几个用列: #python中的函数定义,使用和传参 def_str = '''\ python中的函数以如下形式声明: def 函数名称([参数1,参数2,参数3......]): 执行语 ...
- python 在机器学习中应用函数
浅述python中argsort()函数的用法 (1).先定义一个array数据 1 import numpy as np 2 x=np.array([1,4,3,-1,6,9]) (2).现在我们可 ...
- python unittest框架中addCleanup函数详解
接上一篇doCleanups说明,这次介绍下另一个很好用的函数:addCleanup 还是老规矩,看官方文档说明: addCleanup(function, *args, **kwargs)¶ Add ...
- python 利用matplotlib中imshow()函数绘图
matplotlib 是python最著名的2D绘图库,它提供了一整套和matlab相似的命令API,十分适合交互式地进行制图.而且也可以方便地将它作为绘图控件,嵌入GUI应用程序中.通过简单的绘图语 ...
- (转)python类class中_init_函数以及参数self的简单解释
1)_init_函数(方法) #-*- encoding:utf-8 -*- class NewClass(object): def __init__(self,name): print self s ...
- python通过mongoengine中connect函数连接多个数据库
mongoengine支持程序同时连接多个数据库,这些数据库可以位于一个或多个mongo之中,通过alias名称区分不同的连接即可. 可以通过switch_db切换到不同的数据库,进行读写操作,swi ...
- python和numpy中sum()函数的异同
转载:https://blog.csdn.net/amuchena/article/details/89060798和https://www.runoob.com/python/python-func ...
- Python -- 使用模块中的函数
在确定自己不会导入多个同名函数(从不同模块导入)的情况下,你可能不希望在每次调用函数的时候,都要写上模块的名字.那么,可以使用import命令的另外一种形式: >>> from ma ...
- 关于python使用threadpool中的函数单个参数和多个参数用法举例
1.对单个元素的函数使用线程池: # encoding:utf-8 __author__='xijun.gong' import threadpool def func(name): print 'h ...
- Python函数式编程中map()、reduce()和filter()函数的用法
Python中map().reduce()和filter()三个函数均是应用于序列的内置函数,分别对序列进行遍历.递归计算以及过滤操作.这三个内置函数在实际使用过程中常常和“行内函数”lambda函数 ...
随机推荐
- wordpress自动批量定时发布插件 DX-auto-publish
DX-auto-publish是一款wordpress自动发布插件,方便实用. 该wordpress插件的主要功能如下: 1.能够自动批量定时发布wordpress站点的草稿文章,无需每篇文章都手动设 ...
- ASP.NET 回调技术(CallBack)
在asp.net中客户端与服务器端的交互默认都是整页面提交, 此时客户端将当前页面表单中的数据(包括一些自动生成的隐藏域)都提交到服务器端,服务器重新实例化一个当前页面类的实例响应这个请求,然后将整个 ...
- asihttprequest本机调试时正常,发布后闪退
"Compile sources" -->"Build Phases" 找到ASIFormDataRequest.m和ASIHTTPRequest.m,修 ...
- keil l251 command summary --Lib
keil l251 command summaryLIB251 LIST MYLIB.LIB TO MYLIB.LST PUBLICS LIB251 EXTRACT MYLIB.LIB (GOODCO ...
- 如果你遇到,在IntelliJ IDEA里Ctrl+Alt+方向键用不了
在idea中使用ctrl+b跟踪进入函数之后,每次返回都不知道用什么快捷键,在idea中使用ctrl+alt+方向键首先会出现与win7屏幕方向的快捷键冲突,右键桌面,选择图形属性,将win7的快捷键 ...
- sizeof and strlen整理
sizeof 定义 计算对象或类型所占用的字节数(byte) 记住是字节数,而不是个数 语法 sizeof(对象) int i; sizeof(i); sizeof(类型) sizeof(int); ...
- BZOJ 1006 [HNOI2008] 神奇的国度(简单弦图的染色)
题目大意 K 国是一个热衷三角形的国度,连人的交往也只喜欢三角原则.他们认为三角关系:即 AB 相互认识,BC 相互认识,CA 相互认识,是简洁高效的.为了巩固三角关系,K 国禁止四边关系,五边关系等 ...
- 图文安装Windows Template Library - WTL Version 9.0
从http://wtl.sourceforge.net/下载 WTL 9.0,或者点此链接下载:WTL90_4140_Final.zip,然后解压到你的VC目录下面, 我的地址是:C:\Program ...
- APP-BOM-20516 错误处理一例
昨天在处理一个工单异常时,需要将一个Released的工单改为Unreleased状态,程序报APP-BOM-20516错误,如下图.百度只搜到两条记录,均无用.Google能搜到的多一些,也无用.进 ...
- raphael绘制矢量图2
最近重新再次考虑了下raphael,也没办法把公司的项目给换成raphael的渲染了.大体上的效果稍微考了下其实并不难实现,难点大多集中在对路线以及子路线和方案的转换,以及位置的确定,几乎每操作一步都 ...