python浅学笔记2-函数

学习文档 from https://www.liaoxuefeng.com

  • Python 函数
    • 一些常用函数
    • 定义函数
    • 函数参数
      • 必选参数、默认参数
      • 可变参数
      • 关键字参数
      • 命名关键字参数
      • 参数组合
      • 递归函数
    • ==汉诺塔==

时间戳:2019年3月6日23:38:55

Python 函数

一些常用函数

常用函数调用 abs() max() float() str() bool() hex() isinstance(x,(int,str))

定义函数

定义一个函数 使用关键字 def 例如:

def my_abs(x):
	if x:
		return x
	else:
		return -x

如果没有return语句,函数返回None

定义一个空函数

def nop():
	pass

pass可以作为占位符,充当一个能代替一个将要完成的代码块
在命令行导入某个文件的某个函数 from 文件名 import 函数名

函数可以返回多个值,在return 语句中用 , 隔开 return返回的真是值其实是一个单一的tuple,tuple在return语句中可以省略括号,并且用多个参数来接受这个tuple

函数参数

Python有必选参数、默认参数、可变参数和关键字参数

必选参数、默认参数

def f1(x):  #x为必选参数
	print(x)
def	f2(x,y = 1):	#x为必选参数,y为默认参数,必选在前,默认在后
	print(x,y)
def f3(x = 1,y = 2): 
	print(x,y)
#多个默认参数的调用
f3() # x = 1,y = 2
f3(3) # x = 3,y = 2
f3(3,4) # x = 3,y = 4
f3(y=2) #  x = 1,y = 2

定义默认参数时,参数一定要是不可变参数
如果定义成可变参数会有一个大坑。如:

def f(x = []):
	x.append('end')
	print(x)
f() # 打印['end']
f() # 打印['end','end']
f() # 打印['end','end','end']

发生了什么?在定义函数 f 时,x参数被默认绑定的值 是 指向对象[] 的引用在以后使用默认值调用f时,永远都使用最初定义的那个引用

在Python中不变对象好像很重要的样子,还有多任务环境(是多线程吗)对这些对象处理

可变参数

即函数的参数个数可变

def f(*x):
	for m in x:
		print(m)

f(1) # print(1)
f(1,2,3) # print(1) print(2) print(3)
f(*[1,2,3,4,7]) #调用可变参数的函数,可以用前面标*的 list 或 tuple 传入

可变参数的调用,实质上会把传入的参数在底层包装成一个tuple做处理

关键字参数

即可为函数传入带有参数名的参数,并且参数数量可变,多应用于接口的扩展,让调用者可以提供更多信息
方法,用双*标识参数dict,传入dict的备份

def f(x,**kv):
	print(kw)

f(10,hello = 'jim') #传入了变量hello
extraInfo = {'money':10}
f(**extraInfo)  #传入了变量 money,传入了extraInfo的一个备份,在函数中的操作并不会改变变量extraInfo

命名关键字参数

普通关键字参数,变量名不受限制。如果命名了关键字参数则可以限制关键字参数的名称
方法用一个 *变量 或者 可变参数 *x 变量隔开,这样命名的关键字参数就变成了必选的参数,它们的传入顺序是可变的,当然也可以给关键字参数默认一个值,这样传入时就可缺省该关键字。

def f(x,y,*,city,room):
	pass
	
f(1,2,city = 3,room = 4) 
f(1,2,room = 4,city = 3) 

def ff(x,y,*,city,room = 1):
	pass
	
ff(1,2,city = 3)

参数组合

以上几种参数可以组合起来使用,但是要遵守定义顺序,从前到后,分别是必选参数、默认参数、可变参数、命名关键字参数和关键字参数。

def f(x,y = 1,*args,city,room,desk = 1,**kv):
    print(x,y,args,city,room,desk,kv)
    pass

f(10,11,12,13,city = 20,room = 30) #print: 10 11 (12, 13) 20 30 1 {}

递归函数

函数内部调用函数本身
最经典的是阶乘的计算
n! = 1 * 2 * 3 * 4*…* n
用fact(n)计算结果:

def fact(n):
	if n == 1:
		return 1
	else:
		return n * fact(n-1)

理解 n * fact(n-1)
fact(n-1) 可以视为 (n-1)*fact(n-2)
fact(n-2) 可以视为 (n-2)*fact(n-3) …
归纳, n * (n-1) * (n - 2) * (n - 3)… 2 * f(1)

使用递归函数要注意防止栈溢出,计算机中函数调用是通过栈(stack)结构实现。栈的大小是一定的,类似的比如另一种解释型语言Lua的函数调用栈是200,超过200个函数的调用就会报错。即在lua 调用fact(201) 就会导致程序报错。
为防止函数调用栈溢出,可以使用尾递归进行优化,即 return 后边的表达式只能是函数的调用,不能有其他对函数f的计算。这样每次调用时都退出上一次的调用,只会占用栈的1个位置。但很遗憾的是大多数编程语言包括python都没有对尾调用进行优化

def f(x):
	if x:
		x--
		return f(x)
	else:
		return 1

我测试了一下,如果不使用尾调用,fact(999),就会报错RecursionError: maximum recursion depth exceeded in comparison;使用了尾调用依旧会报同样的错误
尾调用的效果是和循环一样的。python居然没有for的步长循环。

汉诺塔

A B C三个柱子,A柱子套着n个从下到上且从大到小的圆环,B,C 是空柱子,借助B柱,将A柱所有圆环按顺序套在C柱上。移动过程中,每次只能移动一个圆环,并且小圆环上不能套大圆环。
使用递归方法编写函数 move(n,A,B,C)

#aa = {'name':'A','list':[{'id':1},{'id':2},{'id':3}]} #src
#aa = {'name':'A','list':[{'id':1}]} #src
aa = {'name':'A','list':[{'id':1},{'id':2},{'id':3}]} #src
bb = {'name':'B','list':[]} #assist
cc = {'name':'C','list':[]} #dest

def move(n,src,assist,dest):
    if n == 1:
        moveOnce(src,dest)
    else:
        move(n-1,src,dest,assist)
        move(1,src,assist,dest)
        move(n-1,assist,src,dest)
        

def moveOnce(src,dest):
    circle = src['list'].pop()
    dest['list'].append(circle)
    print(src['name'],'-->',dest['name'])
    print(aa,bb,cc)

move(len(aa['list']),aa,bb,cc)

>>>输出:
A --> C
{'name': 'A', 'list': [{'id': 1}, {'id': 2}]} {'name': 'B', 'list': []} {'name': 'C', 'list': [{'id': 3}]}
A --> B
{'name': 'A', 'list': [{'id': 1}]} {'name': 'B', 'list': [{'id': 2}]} {'name': 'C', 'list': [{'id': 3}]}
C --> B
{'name': 'A', 'list': [{'id': 1}]} {'name': 'B', 'list': [{'id': 2}, {'id': 3}]} {'name': 'C', 'list': []}
A --> C
{'name': 'A', 'list': []} {'name': 'B', 'list': [{'id': 2}, {'id': 3}]} {'name': 'C', 'list': [{'id': 1}]}
B --> A
{'name': 'A', 'list': [{'id': 3}]} {'name': 'B', 'list': [{'id': 2}]} {'name': 'C', 'list': [{'id': 1}]}
B --> C
{'name': 'A', 'list': [{'id': 3}]} {'name': 'B', 'list': []} {'name': 'C', 'list': [{'id': 1}, {'id': 2}]}
A --> C
{'name': 'A', 'list': []} {'name': 'B', 'list': []} {'name': 'C', 'list': [{'id': 1}, {'id': 2}, {'id': 3}]}

你可能感兴趣的:(Python浅学)