函数的嵌套调用:
在调用一个函数的过程中,又调用了其他函数
def bar(): print('from bar') def foo(): print('from foo') bar() foo()
函数的嵌套定义:
在一个函数的内部,又定义了另外一个函数
在函数内部定义的名字,只能在内部使用,在外部无法使用
def f1(): x = 1 def f2(): print('from f2') print(x) #打印值 print(f2) #打印内存地址 f2() f1()
名称空间:
存放名字的地方,准确的说是存放名字与变量值绑定关系的地方
又可分为:内置名称空间,全局名称空间,局部名称空间
内置名称空间:
在python解释器启动时产生,存放一些python内置的名字,例如 len(),if
内置名称空间会存在于整个程序运行的始终
全局名称空间:
在执行文件时产生,存放文件级别定义的名字,在文件执行结束后失效,除非中途进行了
例如del x等的命令,x会失效。
x=1
def func(): pass
import os
class Foo: pass
if x==1:z=3
局部名称空间:
在执行文件的过程中,如果调用了该函数,则会产生该函数的局部名称空间,
用来存放该函数内定义的名字,该名字在函数调用时生效,在函数调用结束时失效
三个名称空间的加载顺序:
内置名称空间-->全局名称空间-->局部名称空间
名字的查找顺序:
局部名称空间-->全局名称空间-->内置名称空间
站在局部找max的值
max=1 def foo(): max=2 print(max) foo() # max=2
max=1 def foo(): print(max) foo() # max=1
def foo(): print(max) foo() # <built-in function max> # max()是内置函数,max是内置的函数名
站在全局找max的值
max=1 def foo(): max=2 foo() print(max) # 1
def foo(): max=2 foo() print(max) # <built-in function max>
作用域:
作用的范围
全局作用域:全局存活,全局有效,内置名称空间和全局名称空间的作用域一直到程序结束
局部作用域:临时存活,局部有效
查看全局作用域有哪些名字---->globals()
查看局部作用域有哪些名字---->locals()
x=111111
def f1(): x=1 y=2 def f2():pass print(locals()) print(globals()) f1()
#运行结果
{'f2': <function f1.<locals>.f2 at 0x000001B98D58EF28>, 'y': 2, 'x': 1}
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000001B98D4B9748>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'D:/PyCharm_Projects/day5/a.py', '__cached__': None, 'x': 111111, 'f1': <function f1 at 0x000001B98D3C3E18>}
global关键字和nonlocal关键字:
个人认为global稍微有点儿用,nonlocal在实际应用中并没有什么卵用
x=1 def f1(): x=2 f1() print(x) # x=1
x=1 def f1(): global x # 避免在局部修改全局的名字,所以global 不推荐使用 x=2 f1() print(x) # x=2
l=[] def f2(): l.append('f2') f2() print(l) # ['f2'],为什么不加global就直接能改呢?因为l本身就是可变类型,上面的x是不可变类型,但无论是global还是现在的l.append()方式,都应该避免,函数的执行不要对全局产生影响
x=0 def f1(): x=1 def f2(): x=2 def f3(): global x #这是修改全局,所以最后x=3,但如果想改上面的x=2,该如何修改呢? x=3 f3() f2() f1() print(x)
x=0 def f1(): x=1 def f2(): x=2 def f3(): nonlocal x #修改函数内部正上方的x,跳出当前这一层,并且只在函数内部有效 x=3 f3() print(x) #这里原本是输出2(注释nonlocal x试试),但因为nonlocal x的原因,上层的x=2被更改为x=3 f2() f1() # x=3
x=0 def f1(): x=1 def f2(): # x=2 def f3(): nonlocal x #修改函数内部正上方的x,跳出当前这一层,并且只在函数内部有效 x=3 f3() # print(x) f2() print(x) #同样,注释上面的print(x),就把x=1改为了x=3 f1() # x=3
x=0 def f1(): # x=1 def f2(): # x=2 def f3(): nonlocal x x=3 f3() # print(x) f2() # print(x) f1() #报错,因为nonlocal只能应用在局部使用,要想改全局,使用global
作用域关系在函数定义时就已经固定,与调用位置无关
x=1 def f1(): def f2(): print(x) f2() #f2受层级的限制,只能在这里调用 f1() print(f1())
x=1 def f1(): def f2(): print(x) return f2 #有了函数对象的概念后,就可以把函数返回出来,打破层级的限制,在任意位置调用 func=f1() #在全局定义了func,指向了局部定义的f2的内存地址 print(func)
x=1 def f1(): def f2(): print(x) return f2 func=f1() #找到了全局x,全局的x可能被改掉 x=1000 #在这里全局的x已经被改掉了,不是x=1了, func() # x=1000 。 调用func()在更改x之后发生的,所以这里访问的x仍然是全局的x,但全局的x已经被改了 x=1000 #x=1
x=1 def f1(): def f2(): print(x) return f2 def foo(func): x=3000 func() #func=f2,那么此时x=???, x=1,为什么?因为作用域关系,在函数定义时就已经固定,与调用位置无关 #所以这里的fun()是调用,仍然要回到最原来的定义位置找作用域关系,最原来的位置在 # def f2(): # print(x) 这里的x访问的就是全局的x foo(f1()) #f1()的结果是f2的内存地址
x=1 def f1(): def f2(): print(x) return f2 x=1000 def foo(func): x=3000 func() foo(f1()) # x=1000,调用之前已经被改过了
x=1 def f1(): def f2(): print(x) return f2 def foo(func): x=3000 func() foo(f1()) # 那么此时x=?, x=1 x=1000 #调用完了以后,又修改了全局的x foo(f1()) #x=1000
闭包:
定义在函数内部的函数,包含对外部作用域名字的引用,而不是对全局作用域名字的引用,那么该内部函数就称为闭包函数
x=1 #非此全局作用域 def f1(): x=1111 #包含对外部作用域名字的引用,而不是全局作用域名字的引用,若注释 x=1111,就引用全局作用域了,就不是闭包函数了 def f2(): #定义在函数内部的函数 print(x) return f2 #f2是闭包函数 func=f1() #这里不仅拿到了f2,还拿到了x=1111 func()
x=1 def f1(): x=1111 def f2(): print(x) return f2 func=f1() x=100 func() # x=1111
x=1 def f1(): x=1111 def f2(): print(x) return f2 func=f1() def foo(): x=2222 func() # 不管func放到哪里去运行,都以我自己外面包的那个值为准,都以x=1111为准,相当于f2()捆绑了x=1111 foo() # x=1111
给函数传参的一种方式--->闭包函数
def deco(): x=123 def wrapper(): print(x) return wrapper func=deco()
闭包函数的应用--->惰性计算
传参的方式
import requests def get(url): return requests.get(url).txt print(get('https://www.python.org'))
闭包的方式,不用传参,自己本身就包含了状态
import requests def index(): url='https://www.python.org' def get(): return requests.get(url).text return get python_web=index()
python_web()
但这个函数已经被写死了,如果是要爬取其它的网站呢?
import requests def index(url): #url从这个位置传进来,其实就相当于在内部定义了 url=*********,
# url=********* def get(): return requests.get(url).text return get python_web=index('https://www.python.org') # 从此位置传入 baidu_web=index('https://www.baidu.com') python_web() #python_web拿到了get函数,而且还包括url地址,如index('https://www.python.org') baidu_web() #baidu_web拿到了get函数,而且还包括url地址,如index('https://www.baidu.com')
那么和默认参数有什么区别呢?
默认参数都有一个唯一的值
import requests def get(url='https://www.python.org'): print(requests.get(url).text) get()
好像也没什么问题,但如果爬取百度呢
import requests def get(url='https://www.python.org'): print(requests.get(url).text) get() get('https://www.baidu.com')
需要重新传'https://www.baidu.com',而闭包是什么?是在调用的时候就已经把地址附加给get函数了,所以
python_web拿到的get函数,就已经携带了url地址的get函数,这样每一个函数都包含了自己的一个状态,
默认函数解决不了目前的问题。
装饰器:
为什么用装饰器?
1.开放封闭原则:对扩展是开放的,对修改是封闭的
2.装饰器:为其它添加新功能
装饰器本身可以是可调用对象,被装饰的对象本身也可以是任意可调用对象
装饰器遵循的原则:
1.不修改被装饰对象的源代码
2.不修改被调用对象的调用方式
装饰器的目的:
在遵循原则1和2的前提下,为其它函数添加新功能
一个简单的函数如下
import time def index(): time.sleep(3) print('welcome to index') index()
那么现在统计一下这个函数的运行时间
import time def index(): start=time.time() time.sleep(3) print('welcome to index') stop=time.time() print('run time is %s' %(stop-start)) index()
# welcome to index
# run time is 3.0003116130828857
犯了一个错误,直接修改了源代码
import time def index(): time.sleep(3) print('welcome to index') def wrapper(func): start=time.time() func() stop=time.time() print('run time is %s' % (stop-start)) wrapper(index)
# welcome to index
# run time is 3.007117509841919
运行了,并且加上了新功能,没有更改源代码,但是调用方式更改了,原先是index(),现在是wrapper(index)
装饰器其实就是闭包函数的应用
import time def index(): time.sleep(3) print('welcome to index') def timmer(): func=index def wrapper(): start=time.time() func() stop=time.time() print('run time is %s' % (stop-start)) return wrapper index=timmer() index()
但是如果再加一个home()函数呢?怎么加到上面的代码里面使其具备通用性呢?
def home(): time.sleep(2) print('welcome to home page')
改为如下:
import time def index(): time.sleep(3) print('welcome to index') def home(): time.sleep(2) print('welcome to home page') def timmer(func): # func=index def wrapper(): start=time.time() func() stop=time.time() print('run time is %s' % (stop-start)) return wrapper index=timmer(index) home=timmer(home) index() home()
Python提供了简洁的语法
import time def timmer(func): # func=index def wrapper(): start=time.time() func() stop=time.time() print('run time is %s' % (stop-start)) return wrapper @timmer #index=timmer(index) def index(): time.sleep(3) print('welcome to index') @timmer #home=timmer(home) def home(): time.sleep(2) print('welcome to home page') index() home()
被装饰的对象有什么特点?都是无参函数,但如果是传入参数呢?
@timmer #home=timmer(home) def home(name): time.sleep(2) print('welcome %s to home page'% name)
home('egon') # 报错 wrapper() takes 0positional arguments but 1 was given
home('egon') 相当于wrapper('egon'),但是def wrapper():... 定义时,不需要传参数,所以报错
如何解决?
import time def timmer(func): # func=index def wrapper(name): # name变量是给func用的,所以也需要给func传入name start=time.time() func(name) stop=time.time() print('run time is %s' % (stop-start)) return wrapper # @timmer #index=timmer(index) # def index(): # time.sleep(3) # print('welcome to index') @timmer #home=timmer(home) def home(name): time.sleep(2) print('welcome %s to home page'% name) # index() home('egon')
# welcome egon to home page
# run time is 2.000490427017212
但是index()呢?所以装饰器里面的闭包函数要能适应无参和有参,并且能适应各种形式的传参方式
import time def timmer(func): # func=index def wrapper(*args,**kwargs): #仅更改此部分即可 start=time.time() func(*args,**kwargs) # stop=time.time() print('run time is %s' % (stop-start)) return wrapper @timmer #index=timmer(index) def index(): time.sleep(3) print('welcome to index') @timmer #home=timmer(home) def home(name): time.sleep(2) print('welcome %s to home page'% name) index() home('egon')
目前的情况是index()函数和home()函数都没有返回值,但若给index()函数增加一个返回值呢?
import time def timmer(func): # func=index def wrapper(*args,**kwargs): start=time.time() func(*args,**kwargs) stop=time.time() print('run time is %s' % (stop-start)) return wrapper @timmer #index=timmer(index) def index(): time.sleep(3) print('welcome to index') return 123 @timmer #home=timmer(home) def home(name): time.sleep(2) print('welcome %s to home page'% name) res=index() # res=wrapper()
print(res) # home('egon')
# welcome to index
# run time is 3.0002543926239014
# None 现在index已经不是最原始的index函数了,这里调用的是wrapper函数,所以这里拿到的是wrapper函数的返回值,但是wrapper函数没有返回值
解决返回值的问题
import time def timmer(func): # func=index def wrapper(*args,**kwargs): start=time.time() res=func(*args,**kwargs) #func函数的返回值 stop=time.time() print('run time is %s' % (stop-start)) return res #返回函数的原始函数的返回值 return wrapper @timmer #index=timmer(index) def index(): time.sleep(3) print('welcome to index') return 123 @timmer #home=timmer(home) def home(name): time.sleep(2) print('welcome %s to home page'% name) res=index() print(res) res1=home('egon') print(res1)
实现认证功能的装饰器
def timmer(func): #基本的装饰器形式,基于这种形式可以玩出很多样式 def wrapper(*args,**kwargs): res=func(*args,**kwargs) # func是最原始的函数,想统计时间,上下加时间就好了,想执行认证功能,前面加用户名,密码和if判断即可 return res return wrapper
def auth(func): def wrapper(*args, **kwargs): name=input('name: ').strip() password=input('password: ').strip() if name == 'johnny' and password == '3714': res = func(*args, **kwargs) return res else: print('user or password error') return wrapper @auth # index=auth(index) def index(): print('from index') index() # 实际上执行的是wrapper()
目前是把用户名和密码写死了,那么改为用文件的形式存储用户名和密码
{'alex':'alex3714','egon':'123','wu':'456','johnny':'789'} # db.txt
def auth(func): def wrapper(*args, **kwargs): name=input('name: ').strip() password=input('password: ').strip() with open('db.txt',encoding='utf-8') as f: user_dic = eval(f.read()) #文件中的内容都是字符串的形式 if name in user_dic and password == user_dic[name]: res = func(*args,**kwargs) return res else: print('user or password error') return wrapper @auth # index=auth(index) def index(): print('from index') index() # 实际上执行的是wrapper()
current_user={'user':None} #用来记住用户的状态,默认是没有登陆的 def auth(func): def wrapper(*args, **kwargs): if current_user['user']: #如果账号已经登陆了,记录了状态,就不需要再输入用户名和密码了 return func(*args,**kwargs) name=input('name: ').strip() password=input('password: ').strip() with open('db.txt',encoding='utf-8') as f: user_dic = eval(f.read()) #文件中的内容都是字符串的形式 if name in user_dic and password == user_dic[name]: res = func(*args,**kwargs) current_user['user'] =name # 账户登录后就记住用户的登录状态 return res else: print('user or password error') return wrapper @auth # index=auth(index) def index(): print('from index') @auth def home(name): #再增加一个函数 print('welcome %s'% name) index() # 实际上执行的是wrapper() home('johnny')
以上部分为无参装饰器
以下部分为有参装饰器
若有多种认证类型,该如何解决呢?
current_user={'user':None} def auth(auth_type = 'file'): def deco(func): def wrapper(*args, **kwargs): if auth_type == 'file': if current_user['user']: return func(*args,**kwargs) name=input('name: ').strip() password=input('password: ').strip() with open('db.txt',encoding='utf-8') as f: user_dic = eval(f.read()) if name in user_dic and password == user_dic[name]: res = func(*args,**kwargs) current_user['user'] =name return res else: print('user or password error') elif auth_type == 'mysql': print('mysql') elif auth_type == 'ldap': print('ldap') else: print('invalid auth_type') return wrapper return deco @auth(auth_type='mysql') # @deco ----> # index=deco(index) index拿到的仍然是wrapper函数,没有变 def index(): print('from index')
@auth(auth_type='file')
def home():
print('welcome %s' %name)
index() # wrapper()
home('egon')
# mysql
# name: egon
# password: 123
# user or password error
闭包函数用到三层就已经能满足需求了,因为,最外层已经可以任意传参数了,里面的函数就可以从最外层得到参数
补充:
1.注释信息
import time from functools import wraps #### def timmer(func): @wraps(func) ##### def wrapper(*args,**kwargs): start=time.time() res=func(*args,**kwargs) stop=time.time() print('run time is %s' %(stop-start)) return res return wrapper @timmer #index=timmer(index) def index(): '''这是index函数''' time.sleep(3) print('welcome to index') return 123 print(index.__doc__) # 如果不加上面后面加####的两行,打印出的注释信息就会显示 None
2.一个函数上面可以有多个装饰器
import time from functools import wraps #### current_user={'user':None} def timmer(func): @wraps(func) ##### def wrapper(*args,**kwargs): start=time.time() res=func(*args,**kwargs) stop=time.time() print('run time is %s' %(stop-start)) return res return wrapper def auth(auth_type = 'file'): def deco(func): def wrapper(*args, **kwargs): if auth_type == 'file': if current_user['user']: return func(*args,**kwargs) name=input('name: ').strip() password=input('password: ').strip() with open('db.txt',encoding='utf-8') as f: user_dic = eval(f.read()) if name in user_dic and password == user_dic[name]: res = func(*args,**kwargs) current_user['user'] =name return res else: print('user or password error') elif auth_type == 'mysql': print('mysql') elif auth_type == 'ldap': print('ldap') else: print('invalid auth_type') return wrapper return deco @timmer #index=timmer(index) @auth() # @deco # index=deco(index) #wrapper def index(): '''这是index函数''' time.sleep(3) print('welcome to index') return 123 # print(index.__doc__) index() # name: egon # password: 123 # user or password error # run time is 4.882465362548828
但如果颠倒@timmer和@auth的顺序,则结果会是
# name: alex # password: alex3714 # welcome to index # run time is 3.0001471042633057
迭代器
迭代:是一个重复的过程,每一次重复,都是基于上一次结果而来
先不用for l=['a','b','c','d'] count=0 while count < len(l): print(l[count]) count +=1
重复的过程,每一次的结果都是基于上一次的结果而来的,所以上面就是迭代。取出序列里面的元素就是迭代
什么是序列类型?有顺序的类型,字符串,列表,元祖,但字典不是,所以通过索引的方式只能从序列类型中取数值,那如何从没有索引的类型中取数值呢?比如字典
dic={'name':'johnny','sex':'m','age':'10'}
没有for,for是接下来要写的内容,while能做到吗?while依赖于索引的方式迭代取值的,所以只适用于字符串,列表,元祖,但是对于文件,集合,字典,他们都没有索引,但有这种通过迭代把值取出来的需求。所以必须有一种方式不依赖于索引,这样才能取出字典,文件,集合中的值。Python提供的这种方式就是迭代器
迭代器:提供一种不依赖于索引的取值方式,让迭代非序列类型变为可能
首先什么是可迭代对象(iterable)?
凡是对象下有__iter__方法:对象.__iter__,该对象就是可迭代对象
dic={'name':'johnny','sex':'m','age':'10'} i=dic.__iter__() print(i) # iterator对象 # <dict_keyiterator object at 0x000001D8A9E703B8>
然后有__iter__这个方法,执行一下,执行后的结果就是迭代器对象(iterator),那么有什么用呢?
要解决从字典里面取值,并且不依赖于索引
# i.__next__() # next(i) print(next(i))
print(next(i))
print(next(i))
# name
# sex
# age
把字典的key都取出来了,并且没有依赖索引
但若再执行print(next(i)),就会有 StopIteration 的错误信息
l=['a','b','c','d'] # l 没有__next__方法,只有执行了__iter__方法后的结果才有__next__方法
i=l.__iter__() print(i) # <list_iterator object at 0x000001EA01ABD5C0>
i1=i.__iter__()
print(i1) # <list_iterator object at 0x000001EA01ABD5C0>
所以,迭代器也有__iter__方法,返回的就是本身,并且也是可迭代的对象,有__next__方法
print(next(i)) #a
print(next(i)) #b
print(next(i)) #c
print(next(i)) #d
print(next(i)) # StopIteration
# 没有按照索引取值
l=['a','b','c','d'] iter_l=iter(l) while True: try: print(next(iter_l)) except StopIteration: break # a # b # c # d
dic={'name':'johnny','sex':'m','age':'10'} iter_dic=iter(dic) while True: try: k=next(iter_dic) print(k,dic[k]) except StopIteration: break # name johnny # sex m # age 10
迭代器对象的优点:
1.提供了一种统一的(不依赖于索引的)迭代方式
2.迭代器本身比其他数据类型更省内存
迭代器缺点
1.一次性的,只能往后next,不能回退,不如索引取值灵活
2.无法预知什么时候取值结束,即无法预知长度
for循环的原理
l=['a','b','c','d'] for item in l: # iter_l=l.__iter__() print(item)
for循环就是在用迭代器,for循环先调用这个序列的__iter__方法,所以for只能应用于可迭代的对象,拿到
iter_l这个迭代器后就是用这个迭代器,for循环调用next方法,赋值给item,进行一次循环,一直取到报异常,但不会抛出异常,会使用try,except捕捉到这个异常,结束掉这个循环。
while可不可以实现使用迭代器来循环?但实现起来非常笨拙,自己调用iter方法,变成迭代器,for循环自动做了,并且使用while要自己捕捉异常,for循环也自动做了,所以要迭代一个类型里面的元素,用for循环更合适。
dic={'name':'johnny','sex':'m','age':'10'} iter_dic=iter(dic) while True: try: k=next(iter_dic) print(k,dic[k]) except StopIteration: break
迭代器对象为什么也有iter方法?给for循环准备的。
判断可迭代对象与迭代器对象:
from collections import Iterable,Iterator s='hello' l=['a','b','c','d'] t=('a','b','c','d') dic={'name':'johnny','sex':'m','age':18} set1={1,2,3} f=open('db.txt') print(isinstance(s,Iterable)) print(isinstance(l,Iterable)) print(isinstance(t,Iterable)) print(isinstance(dic,Iterable)) print(isinstance(set1,Iterable)) print(isinstance(f,Iterable)) # True # True # True # True # True # True print(isinstance(s,Iterator)) print(isinstance(l,Iterator)) print(isinstance(t,Iterator)) print(isinstance(dic,Iterator)) print(isinstance(set1,Iterator)) print(isinstance(f,Iterator)) #False #False #False #False #False #True 只有文件是迭代器对象
生成器:
在函数内部包含yield关键字,那么该函数执行的结果就是生成器
def func(): print('first') yield 1111 print('second') yield 2222 print('third') yield 3333 func()
执行此段代码并没有什么输出
def func(): print('first') yield 1111 print('second') yield 2222 print('third') yield 3333 g=func() print(g)
# <generator object func at 0x00000254685A2F10>
def func(): print('first') yield 1111 print('second') yield 2222 print('third') yield 3333
print('fourth') g=func()
print(next(g)) #first print('===>')
print(next(g)) #second
print('===>') print(next(g)) #third
#first
#1111
#===>
#second
#2222
#===>
#third
#3333
def func(): print('first') yield 1111 print('second') yield 2222 print('third') yield 3333 print('fourth') g=func() for i in g: print(i) #first #1111 #second #2222 #third #3333 #fourth
yield的功能:
1.把函数的结果做成迭代器(以一种优雅的方式封装好__iter__,__next__)
def func(n):while True:
yield n n+=1
g=func(0)
for i in g:
print(I)
因为同一时间在内存中只有一个值,所以不会撑爆内存
python3中的range(),也是一个生成器,但是python2不是
现在模拟range()函数
def my_range(start,stop): while True: if start == stop: raise StopIteration yield start start +=1 g=my_range(1,3) print(next(g)) print(next(g)) print(next(g))
def my_range(start,stop): while True: if start == stop: raise StopIteration yield start start +=1 for i in range(1,5): print(i) #1 #2 #3 #4
2.return只能返回一次值,而yield可以返回多次值。函数的暂停和再继续运行的状态是由yield完成的
如何实现linux的tail的功能?
# python3 tail.py -f access.log | grep 'error' (管道解决不同进程之间互相传递数据的问题)
可以使用yield实现管道的功能,利用yield返回多次值的功能
import time def tail(file_path): with open(file_path,'r') 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: if pattern in line: print(line,end='') grep('error',tail('access.log'))
---------------------------------------------------
#追加内容.py
with open('access.log','a') as f: 此文件用来向access.log文件追加内容
f.write('2222error ')
三元表达式:
def foo(x): if x>y: return 'ok' else: return 'no'
等同于
x=10 res='ok' if x > 3 else 'no'
print(res)
def max2(x,y): return x if x > y else y
print(max2(1,3))
列表解析:
l=[] for i in range(10):
if i >=5: l.append('egg%s' % i) print(l)
等同于
l=['egg%s' %i for i in range(10) if i >=5]
print(l)
nums=[1,2,3,4,5,6] nums_new=[item**2 for item in nums if item > 3] print(nums_new)
names=['tom_ab','jerry_ab','henry_','peter_bc'] names_new=[name for name in names if name.endswith('ab')] print(names_new)
# ['tom_ab', 'jerry_ab']
生成器表达式:
用在数据量非常大的场景
l=('egg%s' %I for i in range(1000)) print(l) # <generator object <genexpr> at 0x00000232729C2F10>
print(next(l))
with open('a.txt',encoding='utf-8') as f: #a.txt存放的数据量很大 print(max(len(line) for line in f)) #python提供的简写的方式,而不用max((len(line) for line in f))
with open('a.txt',encoding='utf-8') as f: g=(len(line) for line in f) print(max(g))
#db.txt apple 10 3 tesla 10000 1 mac 3000 2 Lenovo 3000 3 chicken 10 3
with open('db.txt',encoding='utf-8') as f: l=[] for line in f: goods=line.split() price=float(goods[1]) count=int(goods[2]) cost=price * count l.append(cost) print(sum(l))
等同于
with open('db.txt',encoding='utf-8') as f: l=(float(line.split()[1])*int(line.split)[2] for line in f) print(sum(l))
with open('db.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])>=30000] print(info)