python学习笔记(六)抽象(函数)

个人笔记,仅供参考

六、抽象(函数)

在大型项目中,经常有一些功能要重复使用,为了编程的效率,不可能每使用一次就要写一次相关代码。而应该把这些代码写成函数,使用时调用即可。

1、自定义函数

使用def来定义函数

def hello(name):
	return 'Hello, ' + name + '!'

运行这些代码后可以生成一个名为hello的新函数,它返回一个字符串,其中包含向唯一参数指定的人发出问候语。

生成斐波那契数列的函数:

def fibs(num):
	result = [0,1]
	for i in range(num-2):
		result.append(result[-2] + result[-1])
	return result

调用时传递需要生成的数的个数即可

1.1、给函数写文档

有的时候我们拿到一个函数却并不知道怎么用,这就需要在写函数的时候加上文档注释说明用法,不会用的时候查看就好。

def fibs(num):
	'传递要生成数列的长度'
	result = [0,1]
	for i in range(num-2):
		result.append(result[-2] + result[-1])
	return result

如第二行就是文档字符串,如果要多行可以用三个引号。

可以使用如下方法查文档字符串:fibs._doc_

2、参数

不用担心参数的值,编写函数时只要使用参数名称就可以了

参数的本质是变量,在函数内对参数赋值对外部没有影响

2.1、关键字参数和默认值

在调用时使用名称指定的参数称为关键字参数,主要优点是让你不用记各个参数的位置,只用记有哪些参数即可,调用方法如下

fibs(10)
fibs(num=10)

这两种调用方法看起来区别不大,但是在参数很多是关键字参数会很有用

在定义函数的时候可以给变量设置默认值,这样在调用时如果没有指定这个参数,就将按默认值执行,而不是报错。

def fibs(num=10):
	'传递要生成数列的长度'
	result = [0,1]
	for i in range(num-2):
		result.append(result[-2] + result[-1])
	return result

第一行给num指定了默认值10

2.2、收集参数

收集参数可以让用户调用是输入多个参数,函数将多余的参数收集并存在元组中。

def print_param(title,*params):
	print(title)
	print(params)

如以上函数,第一个参数将被传递,而 * 后的参数将被收集并存在元组中。调用如下

print_param('params',1,2,3)

结果如下:

params
(1, 2, 3)

如果要在其他位置设置收集参数,那么在调用时后面的参数就要用关键字参数

2.3、分配参数

与收集参数相反,在调用时使用星号并传递一个元组,将会把元组的值分别传递给各个参数。

3、作用域

变量到底是什么?可以将其视为指向值的名称。因此,执行赋值语句x = 1后,名称x指向值1,这几乎与使用字典时一样,只是你使用的字典“看不见”。其实有一个名为vars的内置函数,它返回这个不可见的字典。

>>> x = 1
>>> scope = vars()
>>> scope['x']
1
>>> scope['x'] += 1
>>> x
2

这个看不见的字典称为命名空间作用域,除全局作用域外,每个函数调用都将创建一个。

>>> def foo(): x = 42
...
>>> x = 1
>>> foo()
>>> x
1

在这里,函数foo创建了变量x,但当你最终查看时,它却没变。这是因为在调用foo是创建了新的命名空间,供foo中的代码块使用。赋值语句x = 42是在这个内部作用域中执行的,不影响外部作用域的x。

如果要在函数中访问全局变量要注意变量的名称没有重复(这样访问容易出bug)

重名时要访问全局变量可以使用glbal指定是全局变量,例如global x指定全局变量x

4、递归

函数调用自己被称为递归,下面是一个递归函数定义:

def recursion():
	return recursion()

这个函数会不断调用自身,最后崩溃。这样的递归被称为无穷递归,因为它从理论上来说永远不会停止。

真正的递归函数要包括以下两部分:

基线条件:满足这种条件时函数将直接返回一个值

递归条件:包含一个或多个调用,这些调用旨在解决问题的一部分

你可能感兴趣的:(python学习笔记,python,抽象类,递归法)