函数

一。为什么要有函数?
1.代码的组织结构不清晰,可读性差。
2.代码冗余度高
3.管理维护难度大,扩展性极差
二。什么是函数?
函数是实现某个功能的代码集合体,其具备一个名称即函数名,通过函数名就可以访问导函数,并执行内部的代码块
举个例子
函数相当于现实生活中的工具,列如扳手,当我们需要拧螺丝时拿出扳手就能很方便的搞定!
但是需要注意:想要使用扳手,就必须要先制造出扳手。
同理:想要使用函数、则必须先定义函数。
所以使用函数时必须遵循 先定义,再调用
三。定义函数
def :定义函数的关键字
函数名:用于查找调用 函数,函数名必须能够体现函所实现的功能,函数名也是名字,与变量名一样,需要遵循命名规范,并且都是用来绑定内存地址
文档注释:用于描述函数的详细信息,可以被help函数提取
代码块:称之为函数体,即函数功能的具体实现代码。
return:函数的返回值

四。函数的三种类型、
1.无参函数
当函数体代码的执行不需要依赖外部的传入数据时
2.有参函数
当函数体的代码逻辑需要外部传入数据时
3.空函数
函数中只有pass时就是空函数,pass表示略过,什么也不干
五。定义阶段与调用阶段
定义阶段发生的事情:
1.申请内存空间存储函数体代码
2.经内存地址与函数的名称进行绑定
需要注意的是,函数的定义阶段不会执行函数体代码,但会检测语法
调用阶段
注意要遵循语法
六。函数的返回值
在函数中使用return关键字来返回值给调用者
当一个功能的执行会产生一个明确的值时,需要使用返回值


函数执行时遇到return立即结束函数执行,无论下面是否有代码

 

函数参数
函数分为两大类:形参与实参
1.形参即在定义函数时,括号内声明的参数。形参本质就是一个变量名,用来接收外部传来的值。
2.实参即在调用函数时,括号内传入的值。实参本质就是变量的值,值可以是常量、变量、表达式或三者的组合。
注意:在调用函数时,实参的值(变量的值)会绑定给形参(变量名),可以在函数内使用形参名,函数调用结束后解除绑定。
定义
#my_sum函数里面的x,y就是形参
def my_sum(x,y):
return x + y
调用
my_sum(10,20) #10,20就是实参
形参和实参又可以分为如下类:
一:位置参数
位置即顺序,在定义阶段从左往右的顺序定义的参数称之为位置形参,位置形参的特点是必须被传值,传入的值不能多也不能少。
定义
#按照从左往右的顺序定义的参数
def user_info(name,age):
str1 = 'my name is %s,my age is %s(name,age)
return str1
调用
#错误示范
user_info()#报错TypeError错误,必须为位置形参(name,age)传值
user_info('owon') #少传值会报错
#正确示范
user_info('owon',19) #my name is owon, my age is 19
位置即顺序,在定义阶段从左往右的顺序传入的值称之为位置实参,位置实参的特点是按照从左往右的顺序与形参一一对应
二:关键字实参
在调用函数阶段按照key=value的形式指明道姓的为指定的形参传值,称之为关键字实参,关键字实参的特点是无顺序,但仍能为指定的形参赋值
定义
def user_info(name,age):
str1 = 'my name is %s, my age is %s' %(name,age)
return str1
调用
usre_info(name='jason', age=20) #输出结果为:my name is jason, my age is 20
user_info(age=20,name='jason') #输出结果为 同上
我们现在学了两种形式的实参,分别是位置实参和关键字实参。在调用函数时可以混合使用但必须注意:
定义
def user_info(name, age):
str1 = 'my name is %s, my age is %s' %(name, age)
return str1
调用
# 大前提:形参name、age都是位置形参,我们无论使用任何格式的实参,都必须为这两个形参传值,但必须注意
# 1 位置实参必须位于关键字实参的左边
user_info('jason', age=20)
user_info(name='jason', 20) # 报错SyntaxError: positional argument follows keyword argument
# 2 不能为同一个形参重复传值
user_info('jason', age=20,name='jason') # 报错TypeError: user_info() got multiple values for argument 'na

 

 

1.三元表达式

符合Python语法的表达方式(形式,公式)称之为表达式

三元,三个元素

总体就是由三个元素组成的表达式

其目的是为了简化书写既然是简化必然有局限性

三元表达式·只能帮你简化两个分支的if 判断,无论这个判断条件是否成立都必须返回一个值

2.递归

指的是递归调用,简单地说就是一个函数在执行是过程直接或间接调用了本身

递归时可能出现以下错误:

在调用函数时超出最大递归深度

Python为了防止递归无限制占用内存,对函数的递归的调用做了最大的层级限制

修改方法

import sys
sys.getrecursionlimit()
sys.setrecursionlimit(2000)  

递归分为回溯和递推

回溯就是从外向里一层一层递归调用下去,

回溯阶段必须要有一个明确的结束条件,每进入下一次递归时,问题的规模都应该有所减少(否则自身毫无意义)

递推就是从里向外一层一层结束递归

总结递归的使用:

1.必须有一个明确的结束条件

2.每次进入更深一层递归时,问题规模相比上次递归都应有所减少

3.递归效率不高,递归层次过多会导致栈溢出(在计算机中,函数调用是通过栈(stack) 这种数据结构实现的,每次进入一个函数调用,栈就会加一层栈,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多就会导致 栈溢出)

二分查找法

​ 分成俩。。。。找不到继续分(前提是从小-----大/从大-----小)

[1,2,10,30,33,99,101,200,301,311,402,403,500,900,1000]
def search(n,l):
   print(l)
   if len(l) == 0:
       print('not exists')
       return
   mid_index=len(l) // 2
   if n > l[mid_index]:
       #in the right
       l=l[mid_index+1:]
       search(n,l)
   elif n < l[mid_index]:
       #in the left
       l=l[:mid_index]
       search(n,l)
   else:
       print('find it')


search(3,l)
l=[1,2,10,30,33,99,101,200,301,402]

def search(num,l,start=0,stop=len(l)-1):
   if start <= stop:
       mid=start+(stop-start)//2
       print('start:[%s] stop:[%s] mid:[%s] mid_val:[%s]' %(start,stop,mid,l[mid]))
       if num > l[mid]:
           start=mid+1
       elif num < l[mid]:
           stop=mid-1
       else:
           print('find it',mid)
           return
       search(num,l,start,stop)
   else: #如果stop > start则意味着列表实际上已经全部切完,即切为空
       print('not exists')
       return

search(301,l)

3.匿名函数

就是没有名字

与函数作用域相同,但是匿名意味着引用计数为0,只能使用一次

lambd 关键字

有名函数:循环使用,保存了名字,通过名字就可以重复引用函数功能

匿名函数:随时定义,一次使用

应用:max ,min ,sorted , map, reduce ,filter

 

posted @ 2019-01-10 23:09  云中一只小雀鸟  阅读(231)  评论(0)    收藏  举报