4.7.1 默认函数定义

最常用的就是为一个或多个参数设定默认值,这让函数可以用比定义时更少的参数来调用,例如:

def ask_ok(prompt, retries=4, complaint='Yes or no, please!'):
while True:
ok = input(prompt)
if ok in ('y', 'ye', 'yes'):
return True
if ok in ('n', 'no', 'nop', 'nope'):
return False
retries = retries - 1
if retries < 0:
raise OSError('uncooperative user')
print(complaint)

可以通过下面几种方式调用:

  • 给定一个必须参数:ask_ok('Do you really want to quit?')
  • 给出一个可选参数:ask_ok('OK to overwrite the file?', 2)
  • 或是给出全部参数:ask_ok('OK to overwrite the file?', 2, 'Come on, only yes or no!')

这个例子同样给出了 in 关键字,即测试一个元组里是否包含给定值。

默认值在 方法定义时 被赋值

i = 5

def f(arg=i):
print(arg) i = 6
f()

所以将会打印 5,因为 i 在方法定义时值为5

注意 ! 默认值只会被赋值一次,所以当默认值是一个可变对象例如List、Dict或多数类时会有不同,这个方法似乎每次总是记住了前一次调用的结果

def f(a, L=[]):
L.append(a)
return L print(f(1))
print(f(2))
print(f(3))

将会打印

[1]
[1, 2]
[1, 2, 3]

如果你不想让默认参数被后续的调用共享,可以这样定义,无论调多少次都不会有问题。

def f(a, L=None):
if L is None:
L = []
L.append(a)
return L

4.7.2 关键字参数

函数同样可以通过 'kwarg=value' 这样的关键字参数形式来调用,如下:

def parrot(voltage, state='a stiff', action='voom', type='Norwegian Blue'):
print("-- This parrot wouldn't", action, end=' ')
print("if you put", voltage, "volts through it.")
print("-- Lovely plumage, the", type)
print("-- It's", state, "!")

这个函数只接受一个必须的参数(voltage),和三个可选参数(state, action, and type),可以通过下面任意方式调用:

parrot(1000)                                          # 1 positional argument
parrot(voltage=1000) # 1 keyword argument
parrot(voltage=1000000, action='VOOOOOM') # 2 keyword arguments
parrot(action='VOOOOOM', voltage=1000000) # 2 keyword arguments
parrot('a million', 'bereft of life', 'jump') # 3 positional arguments
parrot('a thousand', state='pushing up the daisies') # 1 positional, 1 keyword

但下面的调用是不通过的:

parrot()                     # required argument missing
parrot(voltage=5.0, 'dead') # non-keyword argument after a keyword argument
parrot(110, voltage=220) # duplicate value for the same argument
parrot(actor='John Cleese') # unknown keyword argument

在一次函数调用中,关键字参数必须跟在位置参数后面。所有传入的关键字参数必须符合方法能接收的参数(例如parrot方法就不接受actor参数),而顺序并不重要,这当然也包括了必须的参数(比如parrot(voltage=1000)就是通过的)。没有参数可以被第二次接受,所以下面的示例是错误的:

>>> def function(a):
... pass
...
>>> function(0, a=0)
Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: function() got multiple values for keyword argument 'a'

当最后一个参数以 **name 的形式出现,这表示接收一个包含了所有关键字参数的Dictionary字典(看这里介绍)。它还可以结合一个 *name 形式的参数来调用,即接收一个可选参数的元组,注意*name 需出现在 **name 之前。

def cheeseshop(kind, *arguments, **keywords):
print("-- Do you have any", kind, "?")
print("-- I'm sorry, we're all out of", kind)
for arg in arguments:
print(arg)
print("-" * 40)
keys = sorted(keywords.keys())
for kw in keys:
print(kw, ":", keywords[kw])

可以这样调用:

cheeseshop("Limburger", "It's very runny, sir.",
"It's really very, VERY runny, sir.",
shopkeeper="Michael Palin",
client="John Cleese",
sketch="Cheese Shop Sketch")

打印出来这样:

-- Do you have any Limburger ?
-- I'm sorry, we're all out of Limburger
It's very runny, sir.
It's really very, VERY runny, sir.
----------------------------------------
client : John Cleese
shopkeeper : Michael Palin
sketch : Cheese Shop Sketch

值得注意的是,打印出来的关键字参数是通过代码中的 sorted() 方法来排序的,因为Dictionary字典的keys 是无序的,如果不这样做打印出来的参数就是无序的

4.7.3 可变参数

最少使用的是指定函数可以传入可变参数来调用,这些参数被包装在tuple元组中(元组的概念)。

def write_multiple_items(file, separator, *args):
file.write(separator.join(args))

通常这些可变参数出现在形参的最后一个,因为它们会一股脑儿地把所有剩下的参数都传入方法。而任何出现在 *args 可变参数之后的形参必须是关键字参数(‘keyword-only’ arguments),确保它们只能被用作关键字参数而不会被当做可变参数。

>>> def concat(*args, sep="/"):
... return sep.join(args)
...
>>> concat("earth", "mars", "venus")
'earth/mars/venus'
>>> concat("earth", "mars", "venus", sep=".")
'earth.mars.venus'

4.7.4 使用 * 拆分参数列表

相反的情况发生在当参数已经组成一个tuple元组或是list列表却需要拆分成方法所需要的单独的位置参数。例如内置的 range() 方法接收单独的 start 和 stop 两个参数,如果手头只有list或tuple,我们可以用 * 操作符来把list或tuple拆分成关键字。

>>> list(range(3, 6))            # normal call with separate arguments
[3, 4, 5]
>>> args = [3, 6]
>>> list(range(*args)) # call with arguments unpacked from a list
[3, 4, 5]

同样的,Dictionary字典也可用 ** 操作符拆分成关键字

>>> def parrot(voltage, state='a stiff', action='voom'):
... print("-- This parrot wouldn't", action, end=' ')
... print("if you put", voltage, "volts through it.", end=' ')
... print("E's", state, "!")
...
>>> d = {"voltage": "four million", "state": "bleedin' demised", "action": "VOOM"}
>>> parrot(**d)
-- This parrot wouldn't VOOM if you put four million volts through it. E's bleedin' demised !

4.7.5 Lambda表达式

通过Lambda关键字,你可以创建一些简短的匿名function。这个function就返回两个参数之和: lambda a, b: a+b 。Lambda表达式精炼地将function限制在一个表达式中,可以在任何地方替代function object来使用,从语法上来说其实就是Python中常规方法的"语法糖"。与嵌套方法定义相似,lambda表达式能够引用位于function范围内的变量。

>>> def make_incrementor(n):
... return lambda x: x + n
...
>>> f = make_incrementor(42)
>>> f(0)
42
>>> f(1)
43

上面的例子使用Lambda function来返回一个方法,下面的例子是传入Lambda function来代替参数

>>> pairs = [(1, 'one'), (2, 'two'), (3, 'three'), (4, 'four')]
>>> pairs.sort(key=lambda pair: pair[1])
>>> pairs
[(4, 'four'), (1, 'one'), (3, 'three'), (2, 'two')]

4.7.6 文档字符串(Documentation Strings)

对于Doc strings,有一些约定是需要我们去遵守的。

第一行应当是对于方法目的简短且精确的概括。简要来说,既然方法的名称和返回类型可以通过其他方法获得,那么就不用再次明确地说明。
第一行应当以一个大写字母开头,以一个句号结尾。
如果有多行,那么第二行应为空,看起来像是把概括和剩下的描述部分分开。
剩下的行数则是用一行至多行来描述对象的调用规则、副作用等。

Python解释器并不会去除多行文本中的缩进,所以处理Doc strings的工具得自己去做,一般通过下面的约定来完成。
跟在文档第一行后面的第一个非空的行 A 决定了整个文档的缩进列数(我们不使用第一行作为参考是因为它通常是紧靠在文档的三个单引号'''后面,因此看起来并不明显)。相当于缩进长度的空格就被添加在所有行的前部。比 A 缩进列数更少的行不应该出现,但如果出现了,每一行前面所有的空格都会被移除。一个Tab缩进通常相当于8个空格。看下面的代码就很清楚:

>>> def my_function():
... '''Do nothing.
...
... No,really,it doesn't do anything.
... '''
... pass
...
>>> print(my_function.__doc__)
Do nothing. No,really,it doesn't do anything. >>> def less_or_more_indentation_func():
... '''Do something.
...
... second line,normal line
... less indentation line
... more indentation line
... '''
... pass
...
>>> print(less_or_more_indentation_func.__doc__)
Do something. second line,normal line
less indentation line
more indentation line

Python3 官方文档翻译 - 4.7 函数定义的更多相关文章

  1. cocos2dx 关于lua 绑定的环境配置官方文档翻译与 将自己定义c++方法绑定到lua的的方法

    网上有好多写如何讲自己定义的方法绑定到lua的文章,当中都仅仅对环境配置做了简单的介绍,看到有的帖子写在绑定中遇到了各种各样的error.大部分是因为环境配置不对导致的,下面是官方的文档有标准的说明, ...

  2. Python3 官方文档翻译 - 5 数据结构

    这章会更详细地描述了一些你已经学过的知识,同时添加一些新东西. 5.1 List进阶 下面是关于List的所有方法 list.append(x) 将元素添加至列表尾,相当于a[len(a):] = [ ...

  3. Python3.x:函数定义

    Python3.x:函数定义 1,函数定义: def 函数名称([参数1,参数2,参数3......]): 执行语句 2,实例一(不带参数和没返回值): def helloWorld(): print ...

  4. Python3.2官方文档翻译--实例对象和方法对象

    6.3.3 实例对象 如今我们用实例对象做什么呢?实例对象唯一可用的操作就是属性引用.如今有两种合法的属性名称:数据属性和方法. 数据属性相当于smallTalk中的实例变量,C++中的数据成员.数据 ...

  5. python3 参数*args 、 **args 在函数定义和调用中的应用

    一.函数调用时 说明:*args 表示解包(解包 列表.元组.字符串类型) #定义函数cn_musql def cn_musql(host,port,user,pwd,db): print(host) ...

  6. Django 2.0.1 官方文档翻译: 编写你的第一个 Django app,第一部分(Page 6)

    编写你的第一个 Django app,第一部分(Page 6)转载请注明链接地址 Django 2.0.1 官方文档翻译: Django 2.0.1.dev20171223092829 documen ...

  7. 基本控件文档-UITextField属性---iOS-Apple苹果官方文档翻译

    本系列所有开发文档翻译链接地址:iOS7开发-Apple苹果iPhone开发Xcode官方文档翻译PDF下载地址 //转载请注明出处--本文永久链接:http://www.cnblogs.com/Ch ...

  8. 多线程---iOS-Apple苹果官方文档翻译

    本系列所有开发文档翻译链接地址:iOS7开发-Apple苹果iPhone开发Xcode官方文档翻译PDF下载地址(2013年12月29日更新版)   多线程  技术博客http://www.cnblo ...

  9. kong插件官方文档翻译

    kong插件官方文档翻译 目录 介绍 文件结构 编写自定义逻辑 存储配置 访问数据存储 自定义实体 缓存自定义实体 扩展Admin API 编写测试 (卸载)安装你的插件 插件开发 - 介绍 什么是插 ...

随机推荐

  1. iOS 用UISearchDisplayController实现查找功能

    UISearchDisplayController是iOS中用于处理搜索功能的控制器,此控制器需要和UISearchBar结合使用 示例代码如下: // // WKRootViewController ...

  2. JavaSE_ 网络编程 目录(26)

    JavaSE学习总结第26天_网络编程26.01 网络编程概述26.02 网络模型概述和图解26.03 网络编程三要素概述26.04 网络编程三要素之IP概述126.05 InetAddress类的概 ...

  3. C#数据库——用多线程来组合一个SQL语句

    StringBuffer sql = new StringBuffer();或(StringBuilder sql = new StringBuilder ()) sql.Append("s ...

  4. 用CSS样式画横线和竖线的方法

    今天在做网页的时候,需要用到CSS画横线,虽然比较简单,但也出了一些小问题,拿来做个备忘. 方法一:用DIV,代码如下:(推荐此方法)     <div style="width:80 ...

  5. MVC-Easy-UI-datagrid-分页-查询

    时间仓促,代码写的乱,莫怪,着影区不用理会(功能之外) <link href="@Url.Content("~/Content/Site.css")" r ...

  6. 一个帝国cms [!--show.listpage--] css样式

    1.在分页位置加<div class="pagepage">[!--show.listpage--]</div> </div>这个标签 2.在需 ...

  7. 25_Downloading An Image

    一个App,从网上下载一张图片(给出图片地址),重新命名,然后保存到手机中,再从手机中取出显示在屏幕上. 难度不大,就是找图片很蛋疼,百度搜索出来的过一会儿会失效,Google搜索出来的有些需要FQ, ...

  8. UV印刷

    UV就是在一张印上你想要的图案上面过上一层油,主要是增加产品亮度,保护产品表面,其硬度高,耐腐蚀摩擦,不易出现划痕等,有些复膜产品现改为上UV,能达到环保要求,但UV产品不易粘接,有些只能通过局部UV ...

  9. elasearch 版本控制

    http://192.168.32.81:9200/library/books/8/ GET { "_index": "library", "_typ ...

  10. C++模板:二分查找

    bool find(int x,int l,int r){ if(l>r)return false; int mid=(l+r)/2; if(s[mid]==x) return true; el ...