函数进阶

简介:

一、迭代器

1、迭代:是一个重复的过程,每一次重复,都是基于上一次的结果而来

1
2
3
4
5
l = [ 'a' , 'b' , 'c' , 'd' ]
count = 0
while  count <  len (l):
     print (l[count])
     count + = 1

对于列表可以依赖索引取到值,但是数据结构没有索引,比如字典,就需要一种不依赖索引的取值方式,这就需要迭代器了

2、课迭代对象:凡是对象下有__iter__方法,该对象就是可迭代对象(如字符串,列表,字典,集合,元组,文件等)

  迭代器对象:内置有__iter__方法和__next__,得到的结果就是迭代器对象(如文件)


可迭代对象执行__iter__方法变成迭代器对象,执行__next__取到里面的值,每次取一个值

1
2
3
4
5
6
7
8
9
10
11
dic = { 'name' : 'wang' , 'sex' : 'm' , "age" : 18 }
dic_iter = dic.__iter__()
print (dic_iter.__next__())                #打印取到的name
print (dic_iter.__next__())                #打印取到的sex
print (dic_iter.__next__())              #打印取到的age
print (dic_iter.__next__())              #值取完了,抛出异常StopIteration
while  True :
     try :                       #处理异常的用法
         print ( next (dic_iter))
     except  StopIteration:
         break


我们通过这种方式取到的值,用for循环就可以简单做到,for循环的原理就是把数据变成迭代器对象执行,并加入处理异常

二、三元表达式和列表推导式

1、三元表达式

1
2
3
def  my_max(x,y):
     return  if  x > y  else  y          #判断语句在中间,左边写执行语句,右边写else语句
print (my_max( 1 , 3 ))


2、列表推导式

1
2
3
4
l = [ 'egg%s'  % for  in  range ( 10 )]        #列表生成egg0到egg9共十个元素
print (l)
l = [ 'egg%s'  % for  in  range ( 10 )   if  i > = 5 ]      #加上if判断,只取egg5到egg9共五个元素
print (l)

3、列表推导式的优点

方便,改变了编程习惯,可称之为声明式编程

三、生成器

1、生成器就是迭代器,只要在函数内部出现yield关键字,那么再调用该函数,将不会立即执行函数体代码,会得到一个结果,该结果就是生成器对象

2、yield与return比较

  相同点:都有返回值的功能

  不同点:return只能返回一次值,而yield可以返回多次值

3、实现range功能

1
2
3
4
5
6
7
8
9
def  my_range(start,stop):
     while  True :
         if  start  = =  stop:
             raise  StopIteration
         yield  start             #碰到yield,程序会暂停,执行next会得到返回值1,接着往下执行start变成2,接着循环,最后取到的值就是1和2
         start + = 1
g = my_range( 1 , 3 )
for  in  my_range( 1 , 3 ):
     print (i)

4、实现 python3 tail.py -f access.log | grep 'error'功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import  time
def  tail(filepath):
     with  open (filepath,  'r' ) as f:
         f.seek( 0 2 )
         while  True :
             line  =  f.readline()
             if  line:                 #有新的内容,用yield返回,因为yield可以多次返回值
                 yield  line
             else :
                 time.sleep( 0.2 )
def  grep(pattern,lines):
     for  line  in  lines:                  #先查看所有的行,然后找出现error模式的行
         if  pattern  in  line:
             print (line,end = '')
grep( 'error' ,tail( 'access.log' ))

四、面向过程的编程

1、编程思想:核心是过程,即解决问题的步骤,先做什么再做什么,是一种机械式的编程思想

2、优缺点

    优点:复杂问题流程化,进而简单化

    缺点:可扩展性差


五、递归和二分法

1、递归调用:递归调用是函数嵌套调用的一种特殊形式,函数在调用时,直接或间接调用了自身

  递归分为两个阶段:递推,回溯

2、递归的使用:

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

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

 3. 递归效率不高,递归层次过多会导致栈溢出

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

1
2
3
4
5
def  salary(n):
     if  = =  1 :
         return  100
     return  salary(n - 1 ) + 300
print (salary( 5 ))

分析:需要salary(5)的值,返回salary(4)+300,接着取salary(4)的值,一直递推,直到遇到结束条件salary(1)返回值为100,然后回溯,得到salary(5)的值1300

3、二分法

将整个列表切分为两份,取中间值和要找的数据作比较,判断在哪一部分,然后再在那一部分切分,再次取值判断,直到最终找到需要的数据

想从一个按照从小到大排列的数字列表中找到指定的数字,遍历的效率太低,用二分法(算法的一种,算法是解决问题的方法)可以极大低缩小问题规模

六、匿名函数

1、lambda x,y,z=1:x+y+z      #与函数有相同的作用域,但是匿名意味着引用计数为0,使用一次就释放,除非让其有名字

2、有名函数与匿名函数的对比

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

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

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

1
2
3
4
5
6
7
8
9
10
11
salaries = {
     'wang' : 3000 ,
     'li' : 100000 ,
     'tom' : 10000 ,
     'jim' : 2000
}
print ( max (salaries))       #取到的结果是wang
print ( min (salaries))       #取到的结果是jim
可以看到结果不是我们想要的,因为 max min 函数只是把字典的key做比较得到的最大值,最小值,而我们要的是后面的工资的最大值和最小值
print ( max (salaries.values()))     #取到的结果是100000
print ( min (salaries.values()))     #取到的结果是2000

3、用zip函数解决(zip函数也叫拉链函数)

1
2
3
4
5
6
7
8
a = [ 1 , 2 , 3 ]
b = [ 'q' , 'w' , 's' , 'e' ]
res = zip (a,b)
print ( list (res))      #得到的结果是[(1, 'q'), (2, 'w'), (3, 's')],就是把两个列表的元素一一对应,多余的元素不管
解决上面的问题:把上面字典的键值对调
res = zip (salaries.values(),salaries.keys())
print ( max (res))                              #得到最大工资的键值对组成的元组(100000, 'li')
print ( max (res)[ 1 ])                            #得到工资高的人li

4、通常我们都是想取出,工资最高的那个人名,即比较的是salaries的值,得到的是键

1
2
print ( max (salaries,key = lambda  k:salaries[k]))       #取到的结果是li,是我们需要的值
print ( min (salaries,key = lambda  k:salaries[k]))       #取到的结果是jim,是我们需要的值

5、按照薪资高低进行排序sorted

1
2
3
4
res = sorted (salaries,key = lambda  k:salaries[k])
print (res)                      #得到从低到高的顺序['jim', 'wang', 'tom', 'li'] 
如果要求反向排序,即实现从高到低排序
print ( sorted (salaries,key = lambda  k:salaries[k],reverse = True ))      #得到从低到高的顺序['li', 'tom', 'wang', 'jim']

6、map函数,做映射

1
2
3
l = [ 'wang' , 'li' ]
map ( lambda  x:x + '_man' ,l)                    #对列表的每个元素后面添加_man字符串
print ( list ( map ( lambda  x:x + '_man' ,l)))            #得到结果['wang_man', 'li_man']

7、reduce函数 :实现合并

1
2
from  functools  import  reduce         #这个函数需要导入模块
print ( reduce ( lambda  x,y:x + y, range ( 1 , 101 )))      #1到100的和,结果是5050

8、filter函数,实现过滤

1
2
3
l = [ 'wang_man' , 'li_man' , 'tom' ]
res = filter ( lambda  name:name.endswith( 'man' ),l)    #元素里面以字符串man结尾的
print ( list (res))              #过滤的结果['wang_man', 'li_man']

七、内置函数,要看到结果用print打印出来即可

1、数学运算

1
2
3
4
5
6
7
abs ( - 5 )                           # 取绝对值,也就是5
round ( 2.6 )                        # 四舍五入取整,也就是3.0
pow ( 2 3 )                         # 相当于2**3,如果是pow(2, 3, 5),相当于2**3 % 5 结果是3
divmod ( 9 , 2 )                       # 返回除法结果和余数,适用于判断数据需要分多少页
max ([ 1 , 5 , 2 , - 2 ])                     # 求最大值
min ([ 9 , 2 , 1 , 3 ])                     # 求最小值
sum ([ 1 , 2 , 3 ])                      # 求和

2、类型转换

1
2
3
4
5
6
7
8
9
ord ( "A" )   # "A"字符对应的数值
chr ( 65 )   # 数值65对应的字符
bool ( 0 )   # 转换为相应的真假值,在Python中,0相当于False,下列对象都相当于False: [], (), {}, 0, None, 0.0, ''
bin ( 56 )   # 返回一个字符串,表示56的二进制数
hex ( 56 )   # 返回一个字符串,表示56的十六进制数
oct ( 56 )   # 返回一个字符串,表示56的八进制数
list (( 1 2 3 ))    # 转换为列表[1, 2, 3]
tuple ([ 2 3 4 ])   # 转换为(2, 3, 4)
dict (a = 1 , b = "hello" , c = [ 1 2 3 ])   # 构建字典{'a': 1, 'b': 'hello', 'c': [1, 2, 3]}

3、序列操作

1
2
3
4
all ([ True 1 "hello!" ])       # 所有的元素都相当于True值时返回True
any (["",  0 False , [],  None ])   # 有任意一个元素相当于True值时返回True
sorted ([ 1 5 3 ])           # 序列进行排序,也就是[1,3,5]
reversed ([ 1 5 3 ])          # 序列反转,也就是[3,5,1]

4、其他常见内置函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
type ([ 1 , 2 , 3 ])             #[1,2,3]是list类型
len ([ 1 , 2 , 3 ])              #[1,2,3]的长度是3
range ( 1 , 5 , 2 )              #快速生成序列,1到9,步长为2,结果是1和3
enumerate 函数:
l = [ 'a' , 'b' ]
for  in  enumerate (l):
     print (i)            #得到结果是(0, 'a') (1, 'b'),这样可以得到元素对应的索引
eval 函数和 exec 函数
s = '1+2+3'
print ( eval (s))       #eval用来执行表达式,并返回表达式执行的结果,结果是6
print ( exec (s))       #exec用来执行语句,不会返回任何值
print ( eval ( '1+2+x' ,{ 'x' : 3 },{ 'x' : 30 }))        #返回33
print ( exec ( '1+2+x' ,{ 'x' : 3 },{ 'x' : 30 }))       #返回None
print ( eval ( 'for i in range(10):print(i)' ))    #语法错误,eval不能执行表达式
print ( exec ( 'for i in range(10):print(i)' ))    #执行语句,得到语句的结果



本文转自 宋鹏超 51CTO博客,原文链接:http://blog.51cto.com/qidian510/2054419,如需转载请自行联系原作者

相关文章
|
1月前
|
人工智能 自然语言处理 算法
DashText进阶使用方法
基于关键词感知的向量检索,稠密向量和稀疏向量组合搜索DashText,进阶使用详细教程来啦~
|
1月前
|
JavaScript 编译器 API
【C++ 函数和过程 进阶篇】全面掌握C++函数返回值:从入门到精通的实战指南
【C++ 函数和过程 进阶篇】全面掌握C++函数返回值:从入门到精通的实战指南
71 1
|
6月前
|
存储
【C进阶】回调函数(指针进阶2,详解,小白必看)(上)
【C进阶】回调函数(指针进阶2,详解,小白必看)(上)
|
6月前
【C进阶】回调函数(指针进阶2,详解,小白必看)(中)
【C进阶】回调函数(指针进阶2,详解,小白必看)(中)
|
2月前
|
人工智能 C++
C/C++基础知识——函数
C/C++基础知识——函数
35 0
|
8月前
基础知识 函数
基础知识 函数
42 0
|
6月前
|
索引
【C进阶】回调函数(指针进阶2,详解,小白必看)(下)
【C进阶】回调函数(指针进阶2,详解,小白必看)(下)
|
8月前
|
XML Java 编译器
【C++】 C++ 基础进阶【一】易错点
本文章主要分享 C++ 的一些基础和易错点,通过比较好的编程方式和借助编译器,将节省的精力和时间用在重要的事情上。
101 0
|
10月前
函数及相关知识点
函数及相关知识点
|
算法 程序员 编译器
『C语言从入门到进阶』第 ③ 期 - 函数
『C语言从入门到进阶』第 ③ 期 - 函数
68 0