函数-过程-行为-动作:实现了某一功能或某些功能指令的集合。

(1).如何定义函数

格式:
	def 函数名([参数列表]):
		"""
			文档注释
		"""
		函数体
		[return 返回值]   --返回值可以是多个

(2).如何调用函数(函数定义完成后,并不会自己调用,等待调用者调用)

格式:
	函数名([实参列表])
注:
	可以通过 函数名.__doc__ 属性来查看该函数的文档注释,能够了解此函数到底是用来做什么的
	print(函数名.__doc__)

函数的调用过程:函数调用本质就是压栈,调用完成后会进行弹栈
(3).函数的分类
1.以函数是否存在参数:有参数、无参数
2.以是否存在返回值:有返回值、无返回值
3.定义者来分类:系统:python官方定义好的,内置daocpython解释器内部的、第三方:公司 组织 个人 、自定义
(4).变量分类
1.全局(本地local)变量:在Python中,定义在py文件的变量
特点:在代码运行时,变量始终有效(不是手动回收)
2.局部变量:定义在函数中的变量,当函数被垃圾机制回收时,该变量也会被回收掉。
注1:在函数外面不能访问函数内部定义变量(局部变量),反过来说,在函数内部可以访问本地变量(全局变量)。
注2若在函数中要修改全局变量,就要使用关键字global申明(不建议修改全局变量的值).

age=17
def show_info():
	global age
	age=18
	return age
print(show_info())
结果:18

注3:函数弹栈,全局变量不弹栈(全局变量常驻内存)
(5).值传递,引用传递(传递对象)

1.值传递:
	import math
	def getcircle_girth(r):
		""" 计算圆的周长:"""
		if r<=0:
			print("输入的半径非法")
			return None
		else:
			return 2*math.pi*r
	r=float(input("请输入圆的半径:"))
	print(getcircle_girth.__doc__)
	print(getcircle_girth(r))
2.引用传递:强数据类型语言中,函数不允许嵌套、包含函数,弱类型
语言可以让函数的内存地址成为实参,传递到另一个函数的形参中,进
行引用传递。
	def info(fn,msg):
		fn()
		print(msg)
	def print_msg():
		print("我自己定义的函数")
	info(print_msg,"haha")
#将print_msg函数的内存地址作为实参,传递到info函数的形参fn中,
然后通过fn()去调用print_msg函数
结果如下:
			我自己定义的函数
			haha

注1:在弱数据类型语言中,万物皆对象,函数也是对象,所以函数就
可以进行引用传递
注2:函数名称就是指函数本身的内存地址,列表名就是指列表本身的
内存地址,即对象名就是对象本身的内存地址

(6).python中的main函数:写在main函数中的代码并不会导入到其他模块中

print("aaaa")

def show():
	print("bbbb")
if __name__=="__main__":
	show()
结果如下:
			aaaa
			bbbb
注:python代码并不是从main函数入口的!!!python代码是脚本,
是从上而下运行的

(7).函数参数

1.默认值参数:在调用的时候,如果给这个参数赋值了,则按照赋值
的情况算;如果没有赋值,也不报错,按照默认值算。
	def get_cicle_cal(r,PI=3.14):#默认值参数
	   	return 2*PI*r
	r=float(input("请输入圆的半径:"))
	cal=get_circle_cal(r,3.1415926)
	print(cal)
2.可变参数:可以传递多个实际参数,可以传值,也可以不传值
	def show(a,b,*args):
		print(a+b)
		# args以元组的方式将剩余参数封装起来
		print(args)
		print(args[0])
	show(2,3,4,5,6)
结果如下:
			5
			(4, 5, 6)
			4
3.关键字参数(命名参数):可以传值(键值对),也可以不传值
	def show_info(x,**kwargs):
		print(x)
		# kwargs以字典的方式将剩余参数封装起来
		print(kwarges)
		print(kwargs["name"])
		print(kwargs.get("age"))
	show_info(1024,name="python",age=17)
结果如下:
			1024
			{'name': 'python', 'age': 17}
			python
			17
4.万能参数:
	def test(a,b,*args,**kwargs):
		print(a+b)
		print(args)
		print(kwargs)
	test(2,3,4,5,name="python",age=17)
结果如下:
			5
			(4,5)
			{'name':'python','age':17}

注:参数顺序:普通参数,默认值参数,可变参数,关键字参数

(8).函数递归:函数自身调用自身。

前提条件:1.自身调用自身
	     2.必须要有终止条件
注:如果递归中没有结束条件,会形成死循环(python规定最大递归
1000层,因为递归太多,会导致栈内存满,电脑死机)

例题:求和0到100
方法一:
	def get_sum(n,m):
		sum=0
		if n>m:
			n,m=m,n
		for i in range(n,m+1):
			sum+=i
		return sum
	if  __name__=="__main__":
		s=get_sum(100,0)
		print(s)
结果:
		5050
方法二:	
	def  get_sum2(n):
		if n==0:
			return 0
		else:
			return n+get_sum2(n-1)
	print(get_sum2(100))
结果:
		5050

(9).匿名函数:(没有名称的函数)–lambda表达式

格式:
	lambda[参数列表]:代码   #返回值不需要写return

特点:创建的时候就用,当一个函数要使用且使用一次,就可以使用匿名函数,可以优化代码,但也有缺点,降低了可读性,增加了维护性
注:一般lambda,也就是匿名函数,一般表示的是简单的函数(一行或者两行)

def show(fn):
		res=fn(10,20)
		print(res)
	
	show(lambda a,b:a*b)
结果:
		200

(10).偏函数:在python中,我们有时候需要调用某个函数,如果想将该函数中的某个参数设置一个固定值,那么就可以使用偏函数,使用functools模块里的partial()去重构一个函数

格式:
	partial(函数名,参数=固定值)

例题:

#这里我们跟导模块的两种方法结合起来:
方法一:
	import functools  #导入的是functools模块的全部属性和方法
	new_int=functools.partial(int,base=8) #用partial方法时,要用functools模块调用
	print(new_int('23154'))
结果:
		9836
方法二:
	from functools import partial #导入的是functools模块的partial这一个方法
	new_int=partial(int,base=8) #用partial方法时就不用模块调用了
	print(new_int('23154'))
结果:
		9836	
注:int()全局函数里的base参数的默认值是10,如果在某些地方需要
将该参数的默认值修改,就可用到偏函数