函数
面向对象:类--》class
面向过程:过程--》def
函数式编程:函数--》def
函数
定义:
函数是指将一组语句的集合通过一个名字(函数名)封装起来,要想执行这个函数,只需调用其函数名即可
特性:
- 减少重复代码
- 使程序变的可扩展
- 使程序变得易维护
语法定义:
def sayhi():#函数名 print("Hello, I'm nobody!") sayhi() #调用函数
可以带参数----------- #下面这段代码 a,b = 5,8 c = a**b print(c) #改成用函数写 def calc(x,y): res = x**y return res #返回函数执行结果 c = calc(a,b) #结果赋值给c变量 print(c)
python中函数定义方法:
def test(x): "The function definition" x+=1 #泛指代码块部分或程序处理逻辑 return x #return定义返回值 #def定义函数的关键字; test:函数名; ()里面可以定义形参 #""里面是文档描述,这个不是必须有,但强烈建议为函数添加描述信息
return 可返回的值:
1.不写return 返回None
2.返回数=1 直接返回
3.返回数>1 返回一个元祖[ , , ]
4.返回 函数 返回函数的内存地址
注意:函数在执行过程中只要遇到return语句,就会停止执行并返回结果,so 也可以理解为 return 语句代表着函数的结束
函数式编程与面向过程的区别:
#函数定义: def test1(): "testing 1" print("the testing 1") return 0 #过程定义: def test2(): "testing 2" print("the testing 2") #函数调用 x=test1() y=test2() #函数与过程的返回值 print("from the test1 is %s" %x) #函数式编程调用的函数中,x接收的返回值为0 print("from the test2 is %s" %y) #面向过程调用的函数中,y接收的返回值为None #运行结果: #the testing 1 #the testing 2 #from the test1 is 0 #from the test2 is None
(1)面向过程:函数是Python内建支持的一种封装,我们通过把大段代码拆成函数,通过一层一层的函数调用,就可以把复杂任务分解成简单的任务,这种分解可以称之为面向过程的程序设计。函数就是面向过程的程序设计的基本单元。
面向过程编程:是由一个个小的def定义的小的过程拼接在一起得到的。
过程是没有返回值的函数,在Python中隐式的给过程定义返回值为None。
(2)函数式编程:函数式编程中的函数是指数学中的函数,即自变量的映射。也就是说一个函数的值仅决定于函数参数的值,不依赖其他状态。"函数式编程"是一种"编程范式"(programming paradigm),也就是如何编写程序的方法论。主要思想是把运算过程尽量写成一系列嵌套的函数调用。
注:Python对函数式编程提供部分支持。由于Python允许使用变量,因此,Python不是纯函数式编程语言。
举例: 数学表达式:(1 + 2) * 3 - 4
传统的过程式编程:
var a = 1 + 2;
var b = a * 3;
var c = b - 4;
函数式编程要求使用函数,我们可以把运算过程定义为不同的函数,然后写成下面这样:
var result = subtract(multiply(add(1,2), 3), 4);
函数调用
调用方法:
test()执行,()表示调用函数test,()内可以有参数也可以没有
形参和实参:
(1)形参:形式参数,不是实际存在,是虚拟变量,在定义函数和函数体的时候使用形参,目的是在函数调用时接收实参(实参个数,类型应与实参一一对应)
(2)实参:实际参数,调用函数时传给函数的参数,可以是常量,变量,表达式,函数,传给形参
(3)区别:形参是虚拟的,不占用内存空间,.形参变量只有在被调用时才分配内存单元,实参是一个变量,占用内存空间,数据传送单向,实参传给形参,不能形参传给实参
def add(a,b): #a b 是形参 print(a+b) add(5,6) #5 6 是形参
有参函数
位置参数和关键字参数
def test(x,y): print(x) print(y) test(1,2) --->1 2 #位置参数调用,与形参一一对应 test(y=2,x=1) --->1 2 #关键字参数调用,与形参顺序无关 test(3,y=2) ---->3 2 #关键字和位置混合 按照位置参数 test(3,x=2) x test(x=2,3) x #关键字参数不能写在位置参数前面
默认参数
def test(x,y=2) print(x) print(y) test(1) ---->12 test(1,y=3) ----->13 test(1,4) ----->14 #默认参数 调用函数时 可有可无 非必须传递 用途:默认安装值
参数组
def test(*args): print(args) test(1,2,3,4,5) --->(1,2,3,4,5) #可接受多个实参(位置参数) 并放入元组 test(*[1,2,3,4,5]) --->(1,2,3,4,5) -------------------------------------- def test(x,*args): print(x) print(args) test(1,2,3,4,5) --->1 (2,3,4,5) --------------------------------------- def test(**kwargs): print(kwargs) print(kwargs['name']) ---->'a' test('name'='a','age'=18) --->{'name':'a','age':18}#把关键字参数转换成字典 test(**{'name':'a','age':18}) ---------------------------------------- def test(name,**kwargs): print(name) print(kwargs) test('a','age'=18) ---------------------------------------- def test(name,agess=18,**kwargs): print(name) print(agess) print(kwargs) test('a','agess'=3,'name'='a','age'=18)--->a 3 {'name':'a','age':18} test('a',4,'name'='a','age'=18)--->a 4 {'name':'a','age':18} test('a',''name'='a','age'=18,agess'=3,)--->a 3 {'name':'a','age':18} ----------------------------------------- def test(name,ages=18,*args,**kwargs): print(name) print(ages) print(*args) print(kwargs) #*args接受位置参数 **kwargs接收关键字参数
局部变量
全局与局部变量
name = "Alex Li" def change_name(name): print("before change:",name) name = "金角大王,一个有Tesla的男人" #这个函数就是这个变量的作用域 出函数就释放 无法在函数中修改 print("after change", name) change_name(name) print("在外面看看name改了么?",name) --------------------- before change: Alex Li after change 金角大王,一个有Tesla的男人 在外面看看name改了么? Alex Li
如果想修改 用global
name = "Alex Li" def change_name(name): print("before change:",name) global name name = "金角大王,一个有Tesla的男人" print("after change", name) change_name(name) print("在外面看看name改了么?",name) --------------------- before change: Alex Li after change 金角大王,一个有Tesla的男人 在外面看看name改了么? 金角大王,一个有Tesla的男人
注意:只有字符串 整数不可以改 其余列表,字典,集合,类 都可以改
name = ['a','b','c'] def change_name(): name[0] = "d" print( name) change_name() print(name) --------------------- ['d','b','c'] ['d','b','c']
递归
在函数内部,可以调用其他函数。如果一个函数在内部调用自身本身,这个函数就是递归函数。递归函数实际应用案例,二分查找
def calc(n): print(n) if int(n/2) ==0: return n return calc(int(n/2)) calc(10) ------------- 10 5 2 1
递归特性:
1. 必须有一个明确的结束条件
2. 每次进入更深一层递归时,问题规模相比上次递归都应有所减少
3. 递归效率不高,递归层次过多会导致栈溢出(在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出)
匿名函数
匿名函数就是不需要显式的指定函数
#这段代码 def calc(n): return n**n print(calc(10)) #换成匿名函数 calc = lambda n:n**n print(calc(10)) ---------------------- res = map(lambda x:x**2,[1,5,7,4,8]) for i in res: print(i) 1 25 49 16 64
高阶函数
变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数。
def add(x,y,f): return f(x) + f(y) res = add(3,-6,abs) print(res)