DAY4-函数进阶
目录:
一、迭代器
一、迭代的概念
- #迭代器即迭代的工具,那什么是迭代呢?
- #迭代是一个重复的过程,每次重复即一次迭代,并且每次迭代的结果都是下一次迭代的初始值
- while True: #只是单纯地重复,因而不是迭代
- print('===>')
- l=[1,2,3]
- count=0
- while count < len(l): #迭代
- print(l[count])
- count+=1
二 为何要有迭代器?什么是可迭代对象?什么是迭代器对象?
- #1、为何要有迭代器?
- 对于序列类型:字符串、列表、元组,我们可以使用索引的方式迭代取出其包含的元素。但对于字典、集合、文件等类型是没有索引的,若还想取出其内部包含的元素,则必须找出一种不依赖于索引的迭代方式,这就是迭代器
- #2、什么是可迭代对象?
- 可迭代对象指的是内置有__iter__方法的对象,即obj.__iter__,如下
- 'hello'.__iter__
- (1,2,3).__iter__
- [1,2,3].__iter__
- {'a':1}.__iter__
- {'a','b'}.__iter__
- open('a.txt').__iter__
- #3、什么是迭代器对象?
- 可迭代对象执行obj.__iter__()得到的结果就是迭代器对象
- 而迭代器对象指的是即内置有__iter__又内置有__next__方法的对象
- 文件类型是迭代器对象
- open('a.txt').__iter__()
- open('a.txt').__next__()
- #4、注意:
- 迭代器对象一定是可迭代对象,而可迭代对象不一定是迭代器对象
- 调用obj.__iter__()方法,得到的是迭代器对象(对于迭代器对象,执行__iter__得到的仍然是它本身)
三、迭代器对象的使用
- dic={'a':1,'b':2,'c':3}
- iter_dic=dic.__iter__() #得到迭代器对象,迭代器对象即有__iter__又有__next__,但是:迭代器.__iter__()得到的仍然是迭代器本身
- iter_dic.__iter__() is iter_dic #True
- print(iter_dic.__next__()) #等同于next(iter_dic)
- print(iter_dic.__next__()) #等同于next(iter_dic)
- print(iter_dic.__next__()) #等同于next(iter_dic)
- # print(iter_dic.__next__()) #抛出异常StopIteration,或者说结束标志
- #有了迭代器,我们就可以不依赖索引迭代取值了
- #迭代对象值取完了,会报异常退出,可使用try..except避免退出程序
- iter_dic=dic.__iter__()
- while 1:
- try:
- k=next(iter_dic)
- print(dic[k])
- except StopIteration:
- break
- #这么写太丑陋了,需要我们自己捕捉异常,控制next,python这么牛逼,能不能帮我解决呢?能,请看for循环
四、for循环
- #基于for循环,我们可以完全不再依赖索引去取值了
- dic={'a':1,'b':2,'c':3}
- for k in dic:
- print(dic[k])
- #for循环的工作原理
- #1:执行in后对象的dic.__iter__()方法,得到一个迭代器对象iter_dic
- #2: 执行next(iter_dic),将得到的值赋值给k,然后执行循环体代码
- #3: 重复过程2,直到捕捉到异常StopIteration,结束循环
五、迭代器的优缺点
- #优点:
- - 提供一种统一的、不依赖于索引的迭代方式
- - 惰性计算,节省内存
- #缺点:
- - 无法获取长度(只有在next完毕才知道到底有几个值)
- - 一次性的,只能往后走,不能往前退
二、生成器
一、什么是生成器
- #只要函数内部包含有yield关键字,那么函数名()的到的结果就是生成器,并且不会执行函数内部代码
- def func():
- print('====>first')
- yield 1
- print('====>second')
- yield 2
- print('====>third')
- yield 3
- print('====>end')
- g=func()
- print(g) #<generator object func at 0x0000000002184360>
二、生成器就是迭代器
- g.__iter__
- g.__next__
- #2、所以生成器就是迭代器,因此可以这么取值
- res=next(g)
- print(res)
- yield的功能:
- 1、yield为我们提供了一种自定义迭代器对象的方法
- 2、yield与return的区别
1:yield可以返回多次值
2:函数暂停与再继续的状态是由yield帮我们保存的
三、练习
1、自定义函数模拟range(1,7,2)
2、模拟管道,实现功能:tail -f access.log | grep '404'
- #题目一:
- def my_range(start,stop,step=1):
- while start < stop:
- yield start
- start+=step
- #执行函数得到生成器,本质就是迭代器
- obj=my_range(1,7,2) #1 3 5
- print(next(obj))
- print(next(obj))
- print(next(obj))
- print(next(obj)) #StopIteration
- #应用于for循环
- for i in my_range(1,7,2):
- print(i)
- #题目二
- import time
- def tail(filepath):
- with open(filepath,'rb') as f:
- f.seek(0,2)
- while True:
- line=f.readline()
- if line:
- yield line
- else:
- time.sleep(0.2)
- def grep(pattern,lines):
- for line in lines:
- line=line.decode('utf-8')
- if pattern in line:
- yield line
- for line in grep('',tail('access.log')):
- print(line,end='')
- #测试
- with open('access.log','a',encoding='utf-8') as f:
- f.write('出错啦404\n')
- 复制代码
四、协程函数
- #yield关键字的另外一种使用形式:表达式形式的yield
- def eater(name):
- print('%s 准备开始吃饭啦' %name)
- food_list=[]
- while True:
- food=yield food_list
- print('%s 吃了 %s' % (name,food))
- food_list.append(food)
- g=eater('egon')
- g.send(None) #对于表达式形式的yield,在使用时,第一次必须传None,g.send(None)等同于next(g),先将前面的代码执行,暂停在yield处,将yield后面值返回,food赋值先不操作。
- g.send('蒸羊羔') #然后e.send:1 从暂停的位置将值传给yield,food赋值 2、然后与next一样
- g.send('蒸鹿茸')
- g.send('蒸熊掌')
- g.send('烧素鸭')
- g.close()
- g.send('烧素鹅')
- g.send('烧鹿尾')
- #g.close()之后将无法在send传值
五 练习
1、编写装饰器,实现初始化协程函数的功能
2、实现功能:grep -rl 'python' /etc
- #题目一:
- def init(func):
- def wrapper(*args,**kwargs):
- g=func(*args,**kwargs)
- next(g)
- return g
- return wrapper
- @init
- def eater(name):
- print('%s 准备开始吃饭啦' %name)
- food_list=[]
- while True:
- food=yield food_list
- print('%s 吃了 %s' % (name,food))
- food_list.append(food)
- g=eater('egon')
- g.send('蒸羊羔')
- #题目二:
- #注意:target.send(...)在拿到target的返回值后才算执行结束
- import os
- def init(func):
- def wrapper(*args,**kwargs):
- g=func(*args,**kwargs)
- next(g)
- return g
- return wrapper
- @init
- def search(target):
- while True:
- filepath=yield
- g=os.walk(filepath)
- for dirname,_,files in g:
- for file in files:
- abs_path=r'%s\%s' %(dirname,file)
- target.send(abs_path)
- @init
- def opener(target):
- while True:
- abs_path=yield
- with open(abs_path,'rb') as f:
- target.send((f,abs_path))
- @init
- def cat(target):
- while True:
- f,abs_path=yield
- for line in f:
- res=target.send((line,abs_path))
- if res:
- break
- @init
- def grep(pattern,target):
- tag=False
- while True:
- line,abs_path=yield tag
- tag=False
- if pattern.encode('utf-8') in line:
- target.send(abs_path)
- tag=True
- @init
- def printer():
- while True:
- abs_path=yield
- print(abs_path)
- g=search(opener(cat(grep('你好',printer()))))
- # g.send(r'E:\CMS\aaa\db')
- g=search(opener(cat(grep('python',printer()))))
- g.send(r'E:\CMS\aaa\db')
os.walk
六、yield总结
- #1、把函数做成迭代器
- #2、对比return,可以返回多次值,可以挂起/保存函数的运行状态
三、面向过程编程
- #1、首先强调:面向过程编程绝对不是用函数编程这么简单,面向过程是一种编程思路、思想,而编程思路是不依赖于具体的语言或语法的。言外之意是即使我们不依赖于函数,也可以基于面向过程的思想编写程序
- #2、定义
- 面向过程的核心是过程二字,过程指的是解决问题的步骤,即先干什么再干什么
- 基于面向过程设计程序就好比在设计一条流水线,是一种机械式的思维方式
- #3、优点:复杂的问题流程化,进而简单化
- #4、缺点:可扩展性差,修改流水线的任意一个阶段,都会牵一发而动全身
- #5、应用:扩展性要求不高的场景,典型案例如linux内核,git,httpd
- #6、举例
- 流水线1:
- 用户输入用户名、密码--->用户验证--->欢迎界面
- 流水线2:
- 用户输入sql--->sql解析--->执行功能
ps:函数的参数传入,是函数吃进去的食物,而函数return的返回值,是函数拉出来的结果,面向过程的思路就是,把程序的执行当做一串首尾相连的功能,该功能可以是函数的形式,然后一个函数吃,拉出的东西给另外一个函数吃,另外一个函数吃了再继续拉给下一个函数吃。。。
四、三元表达式、列表推导式、生成器表达式
一、三元表达式
- name=input('姓名>>: ')
- res='SB' if name == 'alex' else 'NB'
- print(res)
二、列表推导式
- #1、示例
- egg_list=[]
- for i in range(10):
- egg_list.append('鸡蛋%s' %i)
- egg_list=['鸡蛋%s' %i for i in range(10)]
- #2、语法
- [expression for item1 in iterable1 if condition1
- for item2 in iterable2 if condition2
- ...
- for itemN in iterableN if conditionN
- ]
- 类似于
- res=[]
- for item1 in iterable1:
- if condition1:
- for item2 in iterable2:
- if condition2
- ...
- for itemN in iterableN:
- if conditionN:
- res.append(expression)
- #3、优点:方便,改变了编程习惯,可称之为声明式编程
三、生成器表达式
- #1、把列表推导式的[]换成()就是生成器表达式
- #2、示例:生一筐鸡蛋变成给你一只老母鸡,用的时候就下蛋,这也是生成器的特性
- >>> chicken=('鸡蛋%s' %i for i in range(5))
- >>> chicken
- <generator object <genexpr> at 0x10143f200>
- >>> next(chicken)
- '鸡蛋0'
- >>> list(chicken) #因chicken可迭代,因而可以转成列表
- ['鸡蛋1', '鸡蛋2', '鸡蛋3', '鸡蛋4',]
- #3、优点:省内存,一次只产生一个值在内存中
四、声明式编程练习
1、将names=['egon','alex_sb','wupeiqi','yuanhao']中的名字全部变大写
2、将names=['egon','alex_sb','wupeiqi','yuanhao']中以sb结尾的名字过滤掉,然后保存剩下的名字长度
3、求文件a.txt中最长的行的长度(长度按字符个数算,需要使用max函数)
4、求文件a.txt中总共包含的字符个数?思考为何在第一次之后的n次sum求和得到的结果为0?(需要使用sum函数)
5、思考题
- with open('a.txt') as f:
- g=(len(line) for line in f)
- print(sum(g)) #为何报错?
6、文件shopping.txt内容如下
- mac,20000,3
- lenovo,3000,10
- tesla,1000000,10
- chicken,200,1
求总共花了多少钱?
打印出所有商品的信息,格式为[{'name':'xxx','price':333,'count':3},...]
求单价大于10000的商品信息,格式同上
- #题目一
- names=['egon','alex_sb','wupeiqi','yuanhao']
- names=[name.upper() for name in names]
- #题目二
- names=['egon','alex_sb','wupeiqi','yuanhao']
- names=[len(name) for name in names if not name.endswith('sb')]
- #题目三
- with open('a.txt',encoding='utf-8') as f:
- print(max(len(line) for line in f))
- #题目四
- with open('a.txt', encoding='utf-8') as f:
- print(sum(len(line) for line in f))
- print(sum(len(line) for line in f)) #求包换换行符在内的文件所有的字符数,为何得到的值为0?
- print(sum(len(line) for line in f)) #求包换换行符在内的文件所有的字符数,为何得到的值为0?
- #题目五(略)
- #题目六:每次必须重新打开文件或seek到文件开头,因为迭代完一次就结束了
- with open('a.txt',encoding='utf-8') as f:
- info=[line.split() for line in f]
- cost=sum(float(unit_price)*int(count) for _,unit_price,count in info)
- print(cost)
- with open('a.txt',encoding='utf-8') as f:
- info=[{
- 'name': line.split()[0],
- 'price': float(line.split()[1]),
- 'count': int(line.split()[2]),
- } for line in f]
- print(info)
- with open('a.txt',encoding='utf-8') as f:
- info=[{
- 'name': line.split()[0],
- 'price': float(line.split()[1]),
- 'count': int(line.split()[2]),
- } for line in f if float(line.split()[1]) > 10000]
- print(info)
五、第归与二分法
一、递归调用的定义
- #递归调用是函数嵌套调用的一种特殊形式,函数在调用时,直接或间接调用了自身,就是递归调用
二、递归分为两个阶段:递推、回溯
- #图解。。。
- # salary(5)=salary(4)+300
- # salary(4)=salary(3)+300
- # salary(3)=salary(2)+300
- # salary(2)=salary(1)+300
- # salary(1)=100
- #
- # salary(n)=salary(n-1)+300 n>1
- # salary(1) =100 n=1
- def salary(n):
- if n == 1:
- return 100
- return salary(n-1)+300
- print(salary(5))
三、python中递归的效率低而且没有尾递归优化
- #python中的递归
- python中的递归效率低,需要在进入下一次递归时保留当前的状态,在其他语言中可以有解决方法:尾递归优化,即在函数的最后一步(而非最后一行)调用自己,尾递归优化:http://egon09.blog.51cto.com/9161406/1842475
- 但是python又没有尾递归,且对递归层级做了限制
- #总结递归的使用:
- 1. 必须有一个明确的结束条件
- 2. 每次进入更深一层递归时,问题规模相比上次递归都应有所减少
- 3. 递归效率不高,递归层次过多会导致栈溢出(在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出)
四、可以修改递归最大深度
- import sys
- sys.getrecursionlimit() #查看最大深度
- sys.setrecursionlimit(2000) #修改最大深度
- n=1
- def test():
- global n
- print(n)
- n+=1
- test()
- test()
- 虽然可以设置,但是因为不是尾递归,仍然要保存栈,内存大小一定,不可能无限递归
五、二分法
想从一个按照从小到大排列的数字列表中找到指定的数字,遍历的效率太低,用二分法(算法的一种,算法是解决问题的方法)可以极大低缩小问题规模
- l=[1,2,10,30,33,99,101,200,301,402] #从小到大排列的数字列表
- def search(num,l):
- print(l)
- if len(l) > 0:
- mid=len(l)//2
- if num > l[mid]:
- #in the right
- l=l[mid+1:]
- elif num < l[mid]:
- #in the left
- l=l[:mid]
- else:
- print('find it')
- return
- search(num,l)
- else:
- #如果值不存在,则列表切为空
- print('not exists')
- return
- search(100,l)
实现in的效果
- 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)
实现l.index(30)的效果
六、匿名函数
一、什么是匿名函数
- 匿名就是没有名字
- def func(x,y,z=1):
- return x+y+z
- 匿名
- lambda x,y,z=1:x+y+z #与函数有相同的作用域,但是匿名意味着引用计数为0,使用一次就释放,除非让其有名字。:前是传入参数,:后是返回值
- func=lambda x,y,z=1:x+y+z
- func(1,2,3)
- #让其有名字就没有意义
二、有名字的函数与匿名函数对比
- #有名函数与匿名函数的对比
- 有名函数:循环使用,保存了名字,通过名字就可以重复引用函数功能
- 匿名函数:一次性使用,随时随时定义
- 应用:max,min,sorted,map,reduce,filter
七、内置函数
一、常用内置函数
1、max/min函数
max/min 后直接跟序列会返回此序列的最大/最小值:
- print(max(1,2,3))
max(iterable, key, default) 求迭代器的最大值,其中iterable 为迭代器,max会for i in … 遍历一遍这个迭代器,然后将迭代器的每一个返回值当做参数传给key=func 中的func(一般用lambda表达式定义) ,然后将func的执行结果传给key,然后以key为标准进行大小的判断。
以下根据不同的判断条件返回最大值也不同:
- d1 = {'name': 'egon', 'price': 100}
- d2 = {'name': 'rdw', 'price': 666}
- d3 = {'name': 'zat', 'price': 1}
- l1 = [d1, d2, d3]
- a = max(l1, key=lambda x: x['name'])
- print(a)
- b = max(l1, key=lambda x: x['price'])
- print(b)
结果:
- {'name': 'zat', 'price': 1}
- {'name': 'rdw', 'price': 666}
2、sorted函数
sorted()函数可以接受一个参数
sorted()函数还可以接受一个key函数来实现自定义的排序。
sorted()还可以接受第三个参数:reverse=True,来实现反序排列
- #接受一个参数的例子如下:
- sorted([5,-3,1])——————->结果[-3,1,5] 按大小进行排序
- #接受两个参数:除了要接收要排序的数据,还可以接收一个函数来满足此函数的要求进行排序,例如:
- sorted([5,-3,1],key=abs)————–>结果:[1,-3,5]
- salaries={
- 'egon':3000,
- 'alex':100000000,
- 'wupeiqi':10000,
- 'yuanhao':2000
- }
- print(sorted(salaries,key=lambda k:salaries[k]))
- print(sorted(salaries,key=lambda k:salaries[k],reverse=True))
- ['yuanhao', 'egon', 'wupeiqi', 'alex']
- ['alex', 'wupeiqi', 'egon', 'yuanhao']
3、map函数
用于将一个或多个序列一一对应,转换成另一个序列
格式:
map(func, seq1[, seq2,…])
第一个参数接受一个函数名,后面的参数接受一个或多个可迭代的序列,返回一个迭代器对象。(3之前返回列表)
1、当seq只有一个时,将函数func作用于这个seq的每个元素上,并得到一个新的seq。
- #使用lambda
- g=map(lambda x: x % 2, range(7))
- print(g) #直接打印map函数得到的是内存地址,可以转化成列表查看
- print(list(g))
- <map object at 0x0000000002143F28>
- [0, 1, 0, 1, 0, 1, 0]
- #把这个list所有数字转为字符串:
- print(list(map(str, [1, 2, 3, 4, 5, 6, 7, 8, 9])))
- ['', '', '', '', '', '', '', '', '']
2、当seq多于一个时,map可以并行(注意是并行)地对每个seq执行,每个seq的同一位置的元素同时传入一个多元的func函数之后,得到一个返回值,并将这个返回值存放在一个列表中。下面我们看一个有多个seq的例子:
- g=map(lambda x , y : x ** y, [2,4,6],[3,2,1])
- print(list(g))
- [8, 16, 6]
需要注意的是:
map无法处理seq长度不一致、对应位置操作数类型不一致的情况,这两种情况都会报类型错误。
4、filter函数
用于过滤序列,也接收一个函数和一个序列。和map()
不同的时,filter()
把传入的函数依次作用于每个元素,然后根据返回值是True
还是False
决定保留还是丢弃该元素。
filter函数的第一个参数func
必须返回一个布尔值,即True或者False。
filter(func,seq)
- names=['alex_sb','wupeiqi_sb','yuanhao_sb','egon']
- g=filter(lambda x:x.endswith('sb'),names)
- print(g)
- print(list(g))
- <filter object at 0x0000000001E2C2E8>
- ['alex_sb', 'wupeiqi_sb', 'yuanhao_sb']
5、reduce函数
reduce的用法,reduce把一个函数作用在一个序列[x1, x2, x3...]上,这个函数必须接收两个参数,reduce把结果继续和序列的下一个元素做累积计算,如果有initial,则在序列最开始增加一个初始值,初始值作为序列的第一个元素。
reduce(function, sequence, initial=None)
- from functools import reduce
- print(reduce(lambda x,y:x*10+y,range(1,3),100))
- 10012
6、divmod 函数
函数把除数和余数运算结果结合起来,返回一个包含商和余数的元组(a // b, a % b)。
- divmod(x, y)
x:被除数
y:除数
- print(divmod(5,2))
- (2, 1)
7、enumerate函数
为一个序列生成索引
用法:
enumerate(iterable[, start])
iterable:可迭代对象
start:指定初始值
- l=['a','b','c']
- for i,v in enumerate(l):
- print(i,v)
- 0 a
- 1 b
- 2 c
- l=['a','b','c']
- for i,v in enumerate(l,2):
- print(i,v)
- 2 a
- 3 b
- 4 c
8、eval函数
用来执行一个字符串表达式,并返回表达式的值。
eval(expression[, globals[, locals]])
参数:
expression -- 表达式。
globals -- 变量作用域,全局命名空间,如果被提供,则必须是一个字典对象。
locals -- 变量作用域,局部命名空间,如果被提供,可以是任何映射对象。
- str='2+2'
- print(eval(str))
- 4
- #也可以用于写在文件中的数据还原原本数据类型
- res=eval('[1,2,3]')
- print(res,type(res))
- [1, 2, 3] <class 'list'>
9、exec函数
exec 执行储存在字符串或文件中的Python语句,相比于 eval,exec可以执行更复杂的 Python 代码。
语法:
exec obj
参数
obj -- 要执行的表达式。
返回值
exec 返回值永远为 None。
- >>>exec 'print "Hello World"'
- Hello World
- # 单行语句字符串
- >>> exec "print 'runoob.com'"
- runoob.com
- # 多行语句字符串
- >>> exec """for i in range(5):
- ... print "iter time: %d" % i
- ... """
- iter time: 0
- iter time: 1
- iter time: 2
- iter time: 3
- iter time: 4
- x = 10
- expr = """
- z = 30
- sum = x + y + z
- print(sum)
- """
- def func():
- y = 20
- exec(expr)
- exec(expr, {'x': 1, 'y': 2})
- exec(expr, {'x': 1, 'y': 2}, {'y': 3, 'z': 4})
- func()
- 60
- 33
- 34
- #返回值为空
- res=exec('[1,2,3]')
- print(res)
- None
10、pow函数
内置pow函数是计算x的y次方,如果z在存在,则再对结果进行取模,其结果等效于pow(x,y) %z
注意:pow() 通过内置的方法直接调用,内置方法会把参数作为整型,而 math 模块则会把参数转换为 float。
- #以下是 math 模块 pow() 方法的语法:
- import math
- math.pow( x, y )
内置的 pow() 方法
pow(x, y[, z])
=(x ** y)%z
- import math # 导入 math 模块
- print("math.pow(100, 2) : ", math.pow(100, 2))
- # 使用内置,查看输出结果区别
- print("pow(100, 2) : ", pow(100, 2))
- print("pow(100, -2) : ", pow(100, -2))
- print("math.pow(100, -2) : ", math.pow(100, -2))
- print("math.pow(2, 4) : ", math.pow(2, 4))
- print("math.pow(3, 0) : ", math.pow(3, 0))
结果:
math.pow(100, 2) : 10000.0
pow(100, 2) : 10000
pow(100, -2) : 0.0001
math.pow(100, -2) : 0.0001
math.pow(2, 4) : 16.0
math.pow(3, 0) : 1.0
11、round函数
返回浮点数x的四舍五入值。
round( x [, n] )
参数:
x -- 数值表达式。
n -- 保留后几位。
- #!/usr/bin/python
- print "round(80.23456, 2) : ", round(80.23456, 2)
- print "round(100.000056, 3) : ", round(100.000056, 3)
- print "round(-100.000056, 3) : ", round(-100.000056, 3)
- round(80.23456, 2) : 80.23
- round(100.000056, 3) : 100.0
- round(-100.000056, 3) : -100.0
12、zip()函数
zip() 函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表。
如果各个迭代器的元素个数不一致,则返回列表长度与最短的对象相同,利用 * 号操作符,可以将元组解压为列表。
- zip 语法:
- zip([iterable, ...])
- 参数说明:
- iterabl -- 一个或多个迭代器;
- 返回值
- 返回元组列表。
- >>>a = [1,2,3]
- >>> b = [4,5,6]
- >>> c = [4,5,6,7,8]
- >>> zipped = zip(a,b) # 打包为元组的列表
- [(1, 4), (2, 5), (3, 6)]
- >>> zip(a,c) # 元素个数与最短的列表一致
- [(1, 4), (2, 5), (3, 6)]
- >>> zip(*zipped) # 与 zip 相反,可理解为解压,返回二维矩阵式
- [(1, 2, 3), (4, 5, 6)]
二、了解的内置函数
1、abs(x) 函数返回数字的绝对值。
- print(abs(-45))
- 45
2、all()
函数用于判断给定的可迭代参数 iterable 中的所有元素是否不为 0、''、False 或者 iterable 为空,如果是返回 True,否则返回 False。
注意:空元组、空列表返回值为True,这里要特别注意。
all(iterable)
iterable -- 元组或列表。
- >>>all(['a', 'b', 'c', 'd']) # 列表list,元素都不为空或0
- True
- >>> all(['a', 'b', '', 'd']) # 列表list,存在一个为空的元素
- False
- >>> all([0, 1,2, 3]) # 列表list,存在一个为0的元素
- False
- >>> all(('a', 'b', 'c', 'd')) # 元组tuple,元素都不为空或0
- True
- >>> all(('a', 'b', '', 'd')) # 元组tuple,存在一个为空的元素
- False
- >>> all((0, 1,2, 3)) # 元组tuple,存在一个为0的元素
- False
- >>> all([]) # 空列表
- True
- >>> all(()) # 空元组
- True
3、any()
函数用于判断给定的可迭代参数 iterable 是否全部为空对象,如果都为空、0、false,则返回 False,如果不都为空、0、false,则返回 True。
any(iterable)
iterable--->可迭代元祖或列表
- >>>any(['a', 'b', 'c', 'd']) # 列表list,元素都不为空或0
- True
- >>> any(['a', 'b', '', 'd']) # 列表list,存在一个为空的元素
- True
- >>> any([0, '', False]) # 列表list,元素全为0,'',false
- False
- >>> any(('a', 'b', 'c', 'd')) # 元组tuple,元素都不为空或0
- True
- >>> any(('a', 'b', '', 'd')) # 元组tuple,存在一个为空的元素
- True
- >>> any((0, '', False)) # 元组tuple,元素全为0,'',false
- False
- >>> any([]) # 空列表
- False
- >>> any(()) # 空元组
- False
4、bin函数
返回一个整数 int 或者长整数 long int 的二进制表示。、
bin(x)
x -- int 或者 long int 数字
- >>>bin(10)
- '0b1010'
- >>> bin(20)
- '0b10100'
5、hex() 函数用于将10进制整数转换成16进制整数。
- >>>hex(255)
- '0xff'
- >>> hex(-42)
- '-0x2a'
- >>> hex(1L)
- '0x1L'
6、oct() 函数将一个整数转换成8进制字符串。
- >>>oct(10)
- ''
- >>> oct(20)
- ''
- >>> oct(15)
- ''
- >>>
7、callable() 函数用于检查一个对象是否是可调用的。如果返回True,object仍然可能调用失败;但如果返回False,调用对象ojbect绝对不会成功。
对于函数, 方法, lambda 函式, 类, 以及实现了 __call__ 方法的类实例, 它都返回 True。
- >>>callable(0)
- False
- >>> callable("runoob")
- False
- >>> def add(a, b):
- ... return a + b
- ...
- >>> callable(add) # 函数返回 True
- True
- >>> class A: # 类
- ... def method(self):
- ... return 0
- ...
- >>> callable(A) # 类返回 True
- True
- >>> a = A()
- >>> callable(a) # 没有实现 __call__, 返回 False
- False
- >>> class B:
- ... def __call__(self):
- ... return 0
- ...
- >>> callable(B)
- True
- >>> b = B()
- >>> callable(b) # 实现 __call__, 返回 True
- True
8、chr() 用一个范围在 range(256)内的(就是0~255)整数作参数,返回一个以ascii表对应的字符。
可以是10进制也可以是16进制的形式的数字。
- >>>print chr(0x30), chr(0x31), chr(0x61) # 十六进制
- 0 1 a
- >>> print chr(48), chr(49), chr(97) # 十进制
- 0 1 a
9、ord() 函数是 chr() 函数(对于8位的ASCII字符串)或 unichr() 函数(对于Unicode对象)的配对函数,它以一个字符(长度为1的字符串)作为参数,返回对应的 ASCII 数值,或者 Unicode 数值,如果所给的 Unicode 字符超出了你的 Python 定义范围,则会引发一个 TypeError 的异常。
返回值是对应的十进制整数。
- >>>ord('a')
- 97
- >>> ord('b')
- 98
- >>> ord('c')
- 99
10、dir() 函数不带参数时,返回当前范围内的变量、方法和定义的类型列表;带参数时,返回参数的属性、方法列表。如果参数包含方法__dir__(),该方法将被调用。如果参数不包含__dir__(),该方法将最大限度地收集参数信息。
- dir 语法:
- dir([object])
- 参数说明:
- object -- 对象、变量、类型。
- 返回值:
- 返回模块的属性列表。
- >>>dir() # 获得当前模块的属性列表
- ['__builtins__', '__doc__', '__name__', '__package__', 'arr', 'myslice']
- >>> dir([ ]) # 查看列表的方法
- ['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__delslice__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getslice__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__setslice__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
- >>>
11、frozenset() 返回一个冻结的集合,冻结后集合不能再添加或删除任何元素。
dir 语法:
dir([object])
参数说明:
object -- 对象、变量、类型。
返回值:
返回新的 frozenset 对象,如果不提供任何参数,默认会生成空集合。。
- >>>a = frozenset(range(10)) # 生成一个新的不可变集合
- >>> a
- frozenset([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
- >>> b = frozenset('runoob')
- >>> b
- frozenset(['b', 'r', 'u', 'o', 'n']) # 创建不可变集合
12、hash() 用于获取取一个对象(字符串或者数值等)的哈希值。
- >>>hash('test') # 字符串
- 2314058222102390712
- >>> hash(1) # 数字
- 1
- >>> hash(str([1,2,3])) # 集合
- 1335416675971793195
- >>> hash(str(sorted({'':1}))) # 字典
- 7666464346782421378
- >>>
13、reversed()用于将一个列表元素翻转
- l=[1,2,'a',4]
- print(list(reversed(l)))
- [4, 'a', 2, 1]
与reverse() 不同,reverse() 是直接对源列表进行修改,reversed()是新生成一个翻转的迭代器。
- l=[1,2,'a',4]
- l.reverse()
- print(l)
- [4, 'a', 2, 1]
14、slice() 函数实现切片对象,主要用在切片操作函数里的参数传递。
- slice(stop)
- slice(start, stop[, step])
参数说明:
start -- 起始位置
stop -- 结束位置
step -- 间距
返回值
返回一个切片对象。
- >>>myslice = slice(5) # 设置截取5个元素的切片
- >>> myslice
- slice(None, 5, None)
- >>> arr = range(10)
- >>> arr
- [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
- >>> arr[myslice] # 截取 5 个元素
- [0, 1, 2, 3, 4]
15、vars()函数
vars() 函数返回对象object的属性和属性值的字典对象。
- vars() 函数语法:
- vars([object])
- 参数
- object -- 对象
- 返回值
- 返回对象object的属性和属性值的字典对象,如果没有参数,就打印当前调用位置的属性和属性值 类似 locals()。
- >>>print(vars())
- {'__builtins__': <module '__builtin__' (built-in)>, '__name__': '__main__', '__doc__': None, '__package__': None}
- >>> class Runoob:
- ... a = 1
- ...
- >>> print(vars(Runoob))
- {'a': 1, '__module__': '__main__', '__doc__': None}
- >>> runoob = Runoob()
- >>> print(vars(runoob))
- {}
16、import作用:
导入/引入一个python标准模块,其中包括.py文件、带有__init__.py文件的目录;
__import__作用:
同import语句同样的功能,但__import__是一个函数,并且只接收字符串作为参数,所以它的作用就可想而知了。其实import语句就是调用这个函数进行导入工作的,import sys <==>sys = __import__('sys')
- #实现用户输入选择导入模块
- choice=input('>>: ')
- print(choice,type(choice))
- # import 'time'
- m=__import__(choice)
- m.sleep(10)
- #字符串可以提供的参数 's' None
- >>> format('some string','s')
- 'some string'
- >>> format('some string')
- 'some string'
- #整形数值可以提供的参数有 'b' 'c' 'd' 'o' 'x' 'X' 'n' None
- >>> format(3,'b') #转换成二进制
- ''
- >>> format(97,'c') #转换unicode成字符
- 'a'
- >>> format(11,'d') #转换成10进制
- ''
- >>> format(11,'o') #转换成8进制
- ''
- >>> format(11,'x') #转换成16进制 小写字母表示
- 'b'
- >>> format(11,'X') #转换成16进制 大写字母表示
- 'B'
- >>> format(11,'n') #和d一样
- ''
- >>> format(11) #默认和d一样
- ''
- #浮点数可以提供的参数有 'e' 'E' 'f' 'F' 'g' 'G' 'n' '%' None
- >>> format(314159267,'e') #科学计数法,默认保留6位小数
- '3.141593e+08'
- >>> format(314159267,'0.2e') #科学计数法,指定保留2位小数
- '3.14e+08'
- >>> format(314159267,'0.2E') #科学计数法,指定保留2位小数,采用大写E表示
- '3.14E+08'
- >>> format(314159267,'f') #小数点计数法,默认保留6位小数
- '314159267.000000'
- >>> format(3.14159267000,'f') #小数点计数法,默认保留6位小数
- '3.141593'
- >>> format(3.14159267000,'0.8f') #小数点计数法,指定保留8位小数
- '3.14159267'
- >>> format(3.14159267000,'0.10f') #小数点计数法,指定保留10位小数
- '3.1415926700'
- >>> format(3.14e+1000000,'F') #小数点计数法,无穷大转换成大小字母
- 'INF'
- #g的格式化比较特殊,假设p为格式中指定的保留小数位数,先尝试采用科学计数法格式化,得到幂指数exp,如果-4<=exp<p,则采用小数计数法,并保留p-1-exp位小数,否则按小数计数法计数,并按p-1保留小数位数
- >>> format(0.00003141566,'.1g') #p=1,exp=-5 ==》 -4<=exp<p不成立,按科学计数法计数,保留0位小数点
- '3e-05'
- >>> format(0.00003141566,'.2g') #p=1,exp=-5 ==》 -4<=exp<p不成立,按科学计数法计数,保留1位小数点
- '3.1e-05'
- >>> format(0.00003141566,'.3g') #p=1,exp=-5 ==》 -4<=exp<p不成立,按科学计数法计数,保留2位小数点
- '3.14e-05'
- >>> format(0.00003141566,'.3G') #p=1,exp=-5 ==》 -4<=exp<p不成立,按科学计数法计数,保留0位小数点,E使用大写
- '3.14E-05'
- >>> format(3.1415926777,'.1g') #p=1,exp=0 ==》 -4<=exp<p成立,按小数计数法计数,保留0位小数点
- ''
- >>> format(3.1415926777,'.2g') #p=1,exp=0 ==》 -4<=exp<p成立,按小数计数法计数,保留1位小数点
- '3.1'
- >>> format(3.1415926777,'.3g') #p=1,exp=0 ==》 -4<=exp<p成立,按小数计数法计数,保留2位小数点
- '3.14'
- >>> format(0.00003141566,'.1n') #和g相同
- '3e-05'
- >>> format(0.00003141566,'.3n') #和g相同
- '3.14e-05'
- >>> format(0.00003141566) #和g相同
- '3.141566e-05'
format了解
- 字典的运算:最小值,最大值,排序
- salaries={
- 'egon':3000,
- 'alex':100000000,
- 'wupeiqi':10000,
- 'yuanhao':2000
- }
- 迭代字典,取得是key,因而比较的是key的最大和最小值
- >>> max(salaries)
- 'yuanhao'
- >>> min(salaries)
- 'alex'
- 可以取values,来比较
- >>> max(salaries.values())
- >>> min(salaries.values())
- 但通常我们都是想取出,工资最高的那个人名,即比较的是salaries的值,得到的是键
- >>> max(salaries,key=lambda k:salary[k])
- 'alex'
- >>> min(salaries,key=lambda k:salary[k])
- 'yuanhao'
- 也可以通过zip的方式实现
- salaries_and_names=zip(salaries.values(),salaries.keys())
- 先比较值,值相同则比较键
- >>> max(salaries_and_names)
- (100000000, 'alex')
- salaries_and_names是迭代器,因而只能访问一次
- >>> min(salaries_and_names)
- Traceback (most recent call last):
- File "<stdin>", line 1, in <module>
- ValueError: min() arg is an empty sequence
- sorted(iterable,key=None,reverse=False)
- !!!lambda与内置函数结合使用!!!
!!!lambda与内置函数结合使用!!!
- #1、语法
- # eval(str,[,globasl[,locals]])
- # exec(str,[,globasl[,locals]])
- #2、区别
- #示例一:
- s='1+2+3'
- print(eval(s)) #eval用来执行表达式,并返回表达式执行的结果
- print(exec(s)) #exec用来执行语句,不会返回任何值
- '''
- 6
- None
- '''
- #示例二:
- 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)'))
eval与exec
- compile(str,filename,kind)
- filename:用于追踪str来自于哪个文件,如果不想追踪就可以不定义
- kind可以是:single代表一条语句,exec代表一组语句,eval代表一个表达式
- s='for i in range(10):print(i)'
- code=compile(s,'','exec')
- exec(code)
- s='1+2+3'
- code=compile(s,'','eval')
- eval(code)
complie(了解即可)
练习:
1、文件内容如下,标题为:姓名,性别,年纪,薪资
egon male 18 3000
alex male 38 30000
wupeiqi female 28 20000
yuanhao female 28 10000
要求:
从文件中取出每一条记录放入列表中,
列表的每个元素都是{'name':'egon','sex':'male','age':18,'salary':3000}的形式
2 根据1得到的列表,取出薪资最高的人的信息
3 根据1得到的列表,取出最年轻的人的信息
4 根据1得到的列表,将每个人的信息中的名字映射成首字母大写的形式
5 根据1得到的列表,过滤掉名字以a开头的人的信息
6 使用递归打印斐波那契数列(前两个数的和得到第三个数,如:0 1 1 2 3 4 7...)
7 一个嵌套很多层的列表,如l=[1,2,[3,[4,5,6,[7,8,[9,10,[11,12,13,[14,15]]]]]]],用递归取出所有的值
- #
- with open('db.txt') as f:
- items=(line.split() for line in f)
- info=[{'name':name,'sex':sex,'age':age,'salary':salary} \
- for name,sex,age,salary in items]
- print(info)
- #
- print(max(info,key=lambda dic:dic['salary']))
- #
- print(min(info,key=lambda dic:dic['age']))
- #
- info_new=map(lambda item:{'name':item['name'].capitalize(),
- 'sex':item['sex'],
- 'age':item['age'],
- 'salary':item['salary']},info)
- print(list(info_new))
- #
- g=filter(lambda item:item['name'].startswith('a'),info)
- print(list(g))
- #
- #非递归
- def fib(n):
- a,b=0,1
- while a < n:
- print(a,end=' ')
- a,b=b,a+b
- print()
- fib(10)
- #递归
- def fib(a,b,stop):
- if a > stop:
- return
- print(a,end=' ')
- fib(b,a+b,stop)
- fib(0,1,10)
- #
- l=[1,2,[3,[4,5,6,[7,8,[9,10,[11,12,13,[14,15]]]]]]]
- def get(seq):
- for item in seq:
- if type(item) is list:
- get(item)
- else:
- print(item)
- get(l)
DAY4-函数进阶的更多相关文章
- 深入理解javascript函数进阶系列第一篇——高阶函数
前面的话 前面的函数系列中介绍了函数的基础用法.从本文开始,将介绍javascript函数进阶系列,本文将详细介绍高阶函数 定义 高阶函数(higher-order function)指操作函数的函数 ...
- 【python 3】 函数 进阶
函数进阶 1.函数命名空间和作用域 命名空间一共分为三种: 全局命名空间 局部命名空间 内置命名空间 *内置命名空间中存放了python解释器为我们提供的名字:input , print , str ...
- day11.1函数进阶 列表集合 字典中的函数变量,函数作为形参
函数进阶 1.函数作为变量 a=123 name="gao" nums=[1,2,3] data=nums#指向同一个内存地址 #查看内存地址篇章 def func(): prin ...
- python基础 (初识函数&函数进阶)
函数基础部分 .什么是函数? 函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段. 函数能提高应用的模块性,和代码的重复利用率. 2.定义函数 定义:def 关键词开头,空格之后接函数名 ...
- day 10 - 1 函数进阶
函数进阶 命名空间和作用域 命名空间 命名空间 有三种内置命名空间 —— python解释器 就是python解释器一启动就可以使用的名字存储在内置命名空间中 内置的名字在启动解释器的时候被加载进内存 ...
- python基础之 初识函数&函数进阶
函数基础部分 1.什么是函数? 函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段.函数能提高应用的模块性,和代码的重复利用率. 2.定义函数 定义:def 关键词开头,空格之后接函数名 ...
- python函数进阶(函数参数、返回值、递归函数)
函数进阶 目标 函数参数和返回值的作用 函数的返回值 进阶 函数的参数 进阶 递归函数 01. 函数参数和返回值的作用 函数根据 有没有参数 以及 有没有返回值,可以 相互组合,一共有 4 种 组合形 ...
- python大法好——递归、内置函数、函数进阶
1.递归(自己干自己) def fun(n): n=n/2 print(n) if(n>2) fun(n) #函数调用 fun(10) 结果是5 2 1 0 递归的执行过程:递归执行到最里面一层 ...
- 洗礼灵魂,修炼python(25)--自定义函数(6)—从匿名函数进阶话题讲解中解析“函数式编程”
匿名函数进阶 前一章已经说了匿名函数,匿名函数还可以和其他内置函数结合使用 1.map map():映射器,映射 list(map(lambda x:x*2,range(10))) #把range产生 ...
- 【转】Python之函数进阶
[转]Python之函数进阶 本节内容 上一篇中介绍了Python中函数的定义.函数的调用.函数的参数以及变量的作用域等内容,现在来说下函数的一些高级特性: 递归函数 嵌套函数与闭包 匿名函数 高阶函 ...
随机推荐
- review13
Date与Calendar类 Date类和Calendar类属于java.util包. Date类 1.使用无参数构造方法 使用Date类的无参构造方法创建的对象可以获取本机的当前日期和时间,例如: ...
- Linux软件安装(一)
软件安装方式: 1. rpm方式 该方式软件安装本质与Windows下安装软件方式一致,就是把软件包里面的二进制代码文件复制到系统指定目录(如 C://program files) 优点:软件安装非常 ...
- java开发环境的搭建(JDK的下载安装及环境变量的配置)
首先可以在Sun公司网站 http://java.sun.com 免费下载java se提供的JDK. 下载后再下载的文件夹下打开,双击jdk文件跟着提示进行安装,安装结束后——点击本机电脑的开始—— ...
- MAMP软件的安装和使用
MAMP Pro软件是一款很好的在MAC下面运行的网站集成环境软件,功能强大,配置简单,十分便于本地调试,其由Apache+MySQL+PHP+动态DNS配置构成,PHP的版本可以动态切换到最新版.无 ...
- BZOJ - 2244 拦截导弹 (dp,CDQ分治+树状数组优化)
题目链接 dp进阶之CDQ分治优化dp. 前置技能:dp基本功底,CDQ分治,树状数组. 问题等价于求二维最长上升子序列,是一个三维偏序问题(时间也算一维). 设$dp[i]=(l,x)$为以第i枚导 ...
- C#异步编程(一)线程及异步编程基础
最近试着做了几个.NET CORE的demo,看了些源码,感觉异步编程在Core里面已经成为主流,而对这块我还没有一个系统的总结,所以就出现了这篇文字,接下来几篇文章,我会总结下异步编程的思路,主要参 ...
- webpack 开发环境
当项目逐渐变大,webpack 的编译时间会变长,可以通过参数让编译的输出内容带有进度和颜色. $ webpack --progress --colors 如果不想每次修改模块后都重新编译,那么可以启 ...
- mybatis与oracle使用总结
Oracle使用总结 1.新建表删除表 新建表语句: CREATE TABLE +表名{ } create table AFA_USER ( USER_ID VARCHAR2() not null, ...
- 内存优化总结:ptmalloc、tcmalloc和jemalloc
概述 需求 系统的物理内存是有限的,而对内存的需求是变化的, 程序的动态性越强,内存管理就越重要,选择合适的内存管理算法会带来明显的性能提升.比如nginx, 它在每个连接accept后会malloc ...
- 设置eclipse中jsp/html文件好看的自动排版
注:本文转载于ieayoio,原文链接:https://blog.csdn.net/ieayoio/article/details/49930587#8912689 eclipse中jsp文件代码的排 ...