python3.10官方文档学习记录六__函数

1 定义函数

下列代码创建一个可以输出限定数值内的斐波那契数列函数:

>>> def fib(n): # 将斐波那契级数写到n
... """打印到n的斐波那契数列。""" 
... 	a, b = 0, 1 
... 	while a < n: 
... 		print(a, end=' ') 
... 		a, b = b, a+b 
... 	print() 
... 
>>> # 现在调用刚才定义的函数: 
... fib(2000) 
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597

定义函数使用关键字字def,后跟函数名与括号内的形参列表。
函数语句从下一行开始,并且必须缩进。
函数内的第一条语句是字符串时,该字符串就是文档字符串。利用文档字符串可以自动生成在线文档或打印版文档,还可以让开发者在浏览代码时直接查阅文档;Python开发者最好养成在代码中加入文档字符串的好习惯。
函数在执行时使用函数局部变量符号表,所有函数变量赋值都存在局部符号表中;引用变量时,首先,在局部符号表里查找变量,然后,是外层函数局部符号表,再是全局符号表,最后是内置名称符号表。因此,尽管可以引用全局变量和外层函数的变量,但最好不要在函数内直接赋值(除非是global语句定义的全局变量,或nonlocal语句定义的外层函数变量)。
在调用函数时会将实际参数(实参)引入到被调用函数的局部符号表中;因此,实参是使用按值调用来传递的(其中的值始终是对象的引用而不是对象的值)。
当一个函数调用另外一个函数时,会为该调用创建一个新的局部符号表。
函数定义时在当前符号表中把函数名与函数对象关联在一起。解释器把函数名指向的对象作为用户自定义函数。还可以使用其他名称指向同一个函数对象,并访问访该函数:

>>> fib
<function fib at 10042ed0>
>>> f = fib
>>> f(100)
0 1 1 2 3 5 8 13 21 34 55 89

fib 不返回值。
但是,事实上,没有 return 语句的函数也返回值,只不过这个值是 None (是一个内置名称)。一般来说,解释器不会输出单独的返回值 None ,如需查看该值,可以使用 print() :

>>> fib(0)
>>> print(fib(0))
None

编写不直接输出斐波那契数列运算结果,而是返回运算结果列表的函数也非常简单:

>>> def fib2(n): # 返回到n的斐波那契数列
... """返回包含直到n的斐波那契数列的列表。"""
... result = []
... a, b = 0, 1
... while a < n:
... result.append(a) # see below
... a, b = b, a+b
... return result
...
>>> f100 = fib2(100) # call it
>>> f100 # 写出结果
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]

1、return 语句返回函数的值。 return 语句不带表达式参数时,返回 None 。函数执行完毕退出也返回None 。
2、result.append(a) 语句调用了列表对象 result 的 方法 。方法是“从属于”对象的函数,命名为
obj.methodname , obj 是对象(也可以是表达式), methodname 是对象类型定义的方法名。不同类型定义不同的方法,不同类型的方法名可以相同,且不会引起歧义。(用类可以自定义对象类型和方法)。示例中的方法 append() 是为列表对象定义的,用于在列表末尾添加新元素。本例中,该方法相当于result = result + [a] ,但更有效。

2 函数定义详解

函数定义时,同时支持声明可变数量的参数。这里列出三种可以组合使用的形式(默认值参数,关键字参数,特殊参数)。

2.1 默认值参数

为参数指定默认值是非常有用的方式。指定了默认值参数,在调用函数时,就可以使用比定义时更少的参数,例如:

def ask_ok(prompt, retries=4, reminder='Please try again!'):
	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 ValueError('invalid user response')
 		print(reminder)

上面的函数可以用以下方式调用:
1、只给出必选实参(prompt): ask_ok(‘Do you really want to quit?’)
2、给出一个可选实参(retries): ask_ok(‘OK to overwrite the file?’, 2)
3、给出所有实参(prompt, retries, reminder): ask_ok(‘OK to overwrite the file?’, 2, ‘Come on, only yes or no!’)
4、本例还使用了关键字 in ,用于确认序列中是否包含某个值。
重要警告: 默认值只计算一次。默认值为列表、字典或类实例等可变对象时,会产生与该规则不同的结果。例如,下面的函数会累积后续调用时传递的参数:

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

2.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 和 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

函数调用时,关键字参数必须跟在位置参数后面。不能对同一个参数多次赋值。

2.3 特殊参数

默认情况下,参数可以按位置或显式关键字传递给 Python 函数。为了让代码易读、高效,最好限制参数的传递方式,这样,开发者只需查看函数定义,即可确定参数项是仅按位置、按位置或关键字,还是仅按关键字传递。
函数定义如下:
在这里插入图片描述
/ 和 * 是可选的。这些符号表明形参如何把参数值传递给函数:位置、位置或关键字、关键字。函数定义中未使用 / 和 * 时,参数可以按位置或关键字传递给函数。
特定形参可以标记为 仅限位置。仅限位置 时,形参的顺序很重要,且这些形参不能用关键字传递。仅限位置形参应放在 / (正斜杠)前。 / 用于在逻辑上分割仅限位置形参与其它形参。如果函数定义
中没有 / ,则表示没有仅限位置形参。/ 后可以是 位置或关键字 或 仅限关键字 形参。把形参标记为 仅限关键字,表明必须以关键字参数形式传递该形参,应在参数列表中第一个 仅限关键字 形参前添加* 。
示例
请看下面的函数定义示例,注意 / 和 * 标记:

# 第一个函数定义 standard_arg 是最常见的形式,对调用方式没有任何限制,可以按位置也可以按关键字传递参
# 数:
>>> def standard_arg(arg):
... 	print(arg)
...
# 第二个函数 pos_only_arg 的函数定义中有 / ,仅限使用位置形参:
>>> def pos_only_arg(arg, /):
... 	print(arg)
...
# 第三个函数 kwd_only_args 的函数定义通过 * 表明仅限关键字参数:
>>> def kwd_only_arg(*, arg):
... 	print(arg)
...
# 最后一个函数在同一个函数定义中,使用了全部三种调用惯例:
>>> def combined_example(pos_only, /, standard, *, kwd_only):
... 	print(pos_only, standard, kwd_only)

2.4 文档字符串

第一行应为对象用途的简短摘要。为保持简洁,不要在这里显式说明对象名或类型,因为可通过其他方式获取这些信息(除非该名称碰巧是描述函数操作的动词)。这一行应以大写字母开头,以句点结尾。
文档字符串为多行时,第二行应为空白行,在视觉上将摘要与其余描述分开。后面的行可包含若干段落,描述对象的调用约定、副作用等。
Python 解析器不会删除 Python 中多行字符串字面值的缩进,因此,文档处理工具应在必要时删除缩进。这项操作遵循以下约定:文档字符串第一行之后的第一个非空行决定了整个文档字符串的缩进量(第一行通常与字符串开头的引号相邻,其缩进在字符串中并不明显,因此,不能用第一行的缩进),然后,删除字符串中所有行开头处与此缩进“等价”的空白符。不能有比此缩进更少的行,但如果出现了缩进更少的行,应删除这些行的所有前导空白符。转化制表符后(通常为 8 个空格),应测试空白符的等效性。
下面是多行文档字符串的一个例子:

>>> def my_function():
... 	"""Do nothing, but document it.
 ...
... 	No, really, it doesn't do anything.
... 	"""
... 	pass
...
>>> print(my_function.__doc__)
Do nothing, but document it.

	No, really, it doesn't do anything.

2.5 函数注解

函数注解 是可选的用户自定义函数类型的元数据完整信息
标注 以字典的形式存放在函数的 annotations 属性中,并且不会影响函数的任何其他部分。 形参标注的定义方式是在形参名后加冒号,后面跟一个表达式,该表达式会被求值为标注的值。 返回值标注的定义方式是加组合符号-> ,后面跟一个表达式,该标注位于形参列表和表示 def 语句结束的冒号之间。 下面的示例有一个必须的参数,一个可选的关键字参数以及返回值都带有相应的标注:

>>> def f(ham: str, eggs: str = 'eggs') -> str:
		print("Annotations:", f.__annotations__)

>>> f('spam')
Annotations: {'ham': <class 'str'>, 'return': <class 'str'>, 'eggs': <class 'str'>}

2.6 遵循PEP8编码风格

Python 项目大多都遵循 PEP 8 的风格指南;它推行的编码风格易于阅读、赏心悦目。Python 开发者均应抽时间悉心研读;以下是该提案中的核心要点:
1、缩进,用 4 个空格,不要用制表符。4 个空格是小缩进(更深嵌套)和大缩进(更易阅读)之间的折中方案。制表符会引起混乱,最好别用。
2、换行,一行不超过 79 个字符。这样换行的小屏阅读体验更好,还便于在大屏显示器上并排阅读多个代码文件。
3、用空行分隔函数和类,及函数内较大的代码块。
4、最好把注释放到单独一行。
5、使用文档字符串。
6、运算符前后、逗号后要用空格,但不要直接在括号内使用: a = f(1, 2) + g(3, 4) 。
7、类和函数的命名要一致;按惯例,命名类用 (驼峰原则))UpperCamelCase ,命名函数与方法用lowercase_with_underscores 。命名方法中第一个参数总是用 self (类和方法详见 初探类)。
8、编写用于国际多语环境的代码时,不要用生僻的编码。Python 默认的 UTF-8 或纯 ASCII 可以胜任各种情况。
9、同理,就算多语阅读、维护代码的可能再小,也不要在标识符中使用非 ASCII 字符。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值