装饰器 迭代器 生成器 面相过程 三元表达式 列表解析

装饰器

一 *args,**kwargs

def index(name,age):
print(name,age)

def wrapper(*args,**kwargs):
#args=(1,2,2,3,4,4,5),kwargs={'x':1,'y':2}
index(*args,**kwargs) #index(1,2,2,3,4,4,5,y=2,x=1)

wrapper('egon',age=18)

二 函数对象:函数可被当做数据传递

  • 函数可以当做参数传给另外一个函数
  • 一个函数的返回值也可以是一个函数(打破函数的层级限制)
def f1():
def f2():
print('f2')
return f2
f=f1()
f()

三 名称空间与作用域

名称空间

  • 分三种
  1. 内置名称空间:python解释器启动则生效
  2. 全局名称空间:执行python文件时生效
  3. 局部名称空间:调用函数时,临时生效,函调用结束则失效
  • 加载顺序:先内置,再全局,最后有可能产生局部
  • 查找名字的顺序:先局部,再全局,最后内置

作用:

  • 分两种
  1. 全局作用域:全局存活,全局有效
  2. 局部作用域:临时存活,局部有效

强调:作用关系在函数定义阶段就已经固定,与调用位置无关

闭包函数

  • 定义:定义在函数内部的函数
  • 特点是:包含对外部作用域而不是对全局作用域名字的引用,该函数就称之为闭包函数
x=1
def outter():
x=2
def inner():
print(x)
return inner



 

f=outter()

def f1():
x=1000000000
f()

f1()
from urllib.request import urlopen

#函数体内内部需要一个变量,有两种解决方案
#一种是:以参数的形式传入
def get(url):
return urlopen(url).read()
get('http://www.baidu.com')
get('http://www.baidu.com')
get('http://www.baidu.com')


#另外一种:包起来
def get(url): #url='http://www.baidu.com'
url='http://www.baidu.com'
def inner():
return urlopen(url).read()
return inner

baidu=get('http://www.baidu.com')
print(baidu)
res=baidu()
baidu()
baidu()
baidu()
baidu()

 

 

def get(x,y):
def inner():
print(x,y)
return inner

baidu=get('a','b')

print(baidu.__closure__[0].cell_contents)
print(baidu.__closure__[1].cell_contents)

x,y=1,2
def get():
y=111111
def inner():
print(x,y)
return inner

baidu=get()
print(baidu.__closure__)

 

装饰器

  1. 为什么要用装饰器:开放封闭原则,对扩展是开放的,对修改是封闭的
  2. 什么是装饰器
  • 用来装饰它人,装饰器本身可以是任意可调用对象,被装饰器的对象也可以是任意可调用对象
  • 遵循的原则:1、不修改被装饰对象的源代码 2、不修改被装饰对象的调用方式
  • 目标是:在遵循原则1和2的前提,为被装饰器对象添加上新功能

import time

def timmer(func):
# func=index #最原始的index函数的内存地址
def inner():
start_time=time.time()
func()
stop_time=time.time()
print('run time is :[%s]' %(stop_time-start_time))
return inner

@timmer #index=timmer(index)
def index():
time.sleep(3)
print('welcome to index page')


index()

 


import time
from functools import wraps

def timmer(func):
@wraps(func)
def inner(*args,**kwargs):
start_time=time.time()
res=func(*args,**kwargs)
stop_time=time.time()
print('run time is :[%s]' %(stop_time-start_time))
return res

return inner

@timmer
def index():
'''
index function
:return:
'''
time.sleep(3)
print('welcome to index page')
return 123

@timmer #home=timmer(home) #home=inner
def home(name):
time.sleep(2)
print('welcome %s to home page' %name)
return 456

# res=index() # res=inner()
# print(res)
#
# res=home('egon') #inner('egon')
# print(res)

# print(index.__doc__)
print(help(index))

有参装饰器

import time
current_status={'user':None,'login_status':False}


def auth(func):
def inner(*args,**kwargs):
if current_status['user'] and current_status['login_status']:
res = func(*args, **kwargs)
return res
name=input('username>>:').strip()
pwd=input('password>>:').strip()
if name == 'egon' and pwd == '123':
print('login successfull')
current_status['user']=name
current_status['login_status']=True
res=func(*args,**kwargs)
return res
return inner

@auth #index=auth(index)
def index():
time.sleep(3)
print('welcome to index page')
return 123

@auth
def home(name):
time.sleep(2)
print('welcome %s to home page' %name)
return 456
index()
home('egon')

 

 

import time
current_status={'user':None,'login_status':False}
def auth(egine='file'):
# egine='file'
def wrapper(func):
def inner(*args,**kwargs):
if current_status['user'] and current_status['login_status']:
res = func(*args, **kwargs)
return res

if egine == 'file':
u='egon'
p='123'
elif egine == 'mysql':
print('mysql auth')
u = 'egon'
p = '123'
elif egine == 'ldap':
print('ldap auth')
else:
pass
name = input('username>>:').strip()
pwd = input('password>>:').strip()
if name == u and pwd == p:
print('login successfull')
current_status['user'] = name
current_status['login_status'] = True
res = func(*args, **kwargs)
return res
return inner
return wrapper
@auth(egine='ldap') #@wrapper #index=wrapper(index) #index=inner
def index():
time.sleep(3)
print('welcome to index page')
return 123

 

index() #inner()

多个装饰器

import time
current_status={'user':None,'login_status':False}

def timmer(func):
def inner(*args,**kwargs):
start_time=time.time()
res=func(*args,**kwargs)
stop_time=time.time()
print('run time is :[%s]' %(stop_time-start_time))
return res

return inner

def auth(egine='file'):
# egine='file'
def wrapper(func):
def inner(*args,**kwargs):
if current_status['user'] and current_status['login_status']:
res = func(*args, **kwargs)
return res

if egine == 'file':
u='egon'
p='123'
elif egine == 'mysql':
u = 'egon'
p = '123'
elif egine == 'ldap':
u = 'egon'
p = '123'
else:
pass
name = input('username>>:').strip()
pwd = input('password>>:').strip()
if name == u and pwd == p:
print('login successfull')
current_status['user'] = name
current_status['login_status'] = True
res = func(*args, **kwargs)
return res
return inner
return wrapper


@timmer
@auth(egine='ldap') #@wrapper #index=wrapper(timmer_inner)
# @timmer #timmer_inner=timmer(index)
def index():
time.sleep(3)
print('welcome to index page')
return 123


index() #inner()

迭代器

1 什么叫迭代:迭代是一个重复过程,每次重复都是基于上一次的结果来的
2 为什么要用迭代器?

l=['a','b','c']
n=0
while n < len(l):
print(l[n])
n+=1
  • 对于序列类型:字符串,列表,元组,可以使用基于索引的迭代取值方式,而对于没有索引的类型,如字典,
    集合、文件,这种方式不再适用,于是我们必须找出一种能不依赖于索引的取值方式,这就是迭代器

3 可迭代的对象:只要对象内置有__iter__方法,obj.iter
4 迭代器对象:对象既内置有__iter__方法,又内置有__next__,如文件对象
注意:可迭代对象不一定是迭代器对象,而迭代器对象一定是可迭代的对象

可迭代的对象

'hello'.__iter__
[1,2].__iter__
(1,2).__iter__
{'a':1}.__iter__
{1,2,3}.__iter__

既是可迭代对象,又是迭代器对象

open('a.txt','w').__iter__
open('a.txt','w').__next__

迭代器对象执行__iter__得到的仍然是它本身

dic={'a':1,'b':2,'c':3}
iter_dic=dic.__iter__()

print(iter_dic.__iter__() is iter_dic)

 

f=open('a.txt','w')
print(f is f.__iter__())

迭代器对象的用处

dic={'a':1,'b':2,'c':3}
iter_dic=dic.__iter__()


print(iter_dic.__next__())
print(next(iter_dic))
print(next(iter_dic))
print(next(iter_dic)) #StopIteration


with open('a.txt','r') as f:
print(next(f))
print(next(f))
print(next(f))


l=[1,2,3,4,5]
iter_l=l.__iter__()
print(iter_l)
print(next(iter_l))
print(next(iter_l))
print(next(iter_l))

基于迭代器对象的迭代取值(不依赖索引)

dic={'a':1,'b':2,'c':3}

iter_dic=dic.__iter__()
obj=range(1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000)

list(obj)


while True:
try:
i=next(iter_dic)
print(i)
except StopIteration:
break


for i in dic: #iter_dic=dic.__iter__()
print(i)

迭代器的优缺点:

  • 优点:
    提供了一种统一的迭代取值方式,该方式不再依赖于索引
    更节省内存

  • 缺点:
    无法统计长度
    一次性的,只能往后走,不能往前退,无法获取指定位置的值

from collections import Iterable,Iterator

print(isinstance('hello',Iterable))
print(isinstance('hello',Iterator))

生成器

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



def func():
print('===>first')
yield 1
print('===>second')
yield 2
print('====>third')
yield 3


g=func()
print(g)

#生成器本质就是迭代器
print(next(g))
print(next(g))
print(next(g))
print(next(g))


print(next(func()))
print(next(func()))
print(next(func()))




for i in g:
print(i)

for i in g:
print(i)

for i in g:
print(i)

yield的功能:

  • 为我们提供了一种自定义迭代器的方式
  • 对比return,可以返回多次值,挂起函数的运行状态
#自定义功能,可以生成无穷多个值,因为同一时间在内存中只有一个值
def my_range(start,stop,step=1):
while start < stop:
yield start
start+=step


g=my_range(1,5,2) #1 3
print(next(g))
print(next(g))
print(next(g))
print(next(g))
print(next(g))
for i in my_range(1,1000000000000000000000000000000000000000000,step=2):
print(i)

 


tail -f access.log | grep '404'
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

g=grep('404',tail('access.log'))
for line in g:
print(line)

yield的表达式形式的应用

def eater(name):
food_list=[]
print('%s 开动啦' %name)
while True:
food=yield food_list #food=‘骨头’
print('%s 开始吃 %s' %(name,food))
food_list.append(food)

g=eater('alex')

g.send(None) #next(g)
print(g.send('骨头'))
print(g.send('shi'))



def f1():
while True:
x=yield
print(x)

g=f1()
next(g)
g.send(1)
g.send(1)
g.close()
g.send(1)
g.send(1)
g.send(1)

面相过程编程

'''
强调:面向过程编程绝对不是用函数编程那么简单

  • 面向过程的编程思想:核心是过程二字,过程即解决问题的步骤,即先干什么再干什么

  • 基于该思想去编写程序就好比在设计一条流水线,是一种机械式的编程思想

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

  • 缺点:可扩展性差

import os
g=os.walk(r'C:\Users\Administrator\PycharmProjects\19期\day4\a')
for dirname,_,files in g:
for file in files:
abs_file_path=r'%s\%s' %(dirname,file)
print(abs_file_path)


#grep -rl 'root' /etc
import os
def init(func):
def inner(*args,**kwargs):
g=func(*args,**kwargs)
next(g)
return g
return inner

def search(filepath,target): #找到一个文件路径就往下个阶段传一次
g = os.walk(filepath)
for dirname, _, files in g:
for file in files:
abs_file_path = r'%s\%s' % (dirname, file)
target.send(abs_file_path)

@init
def opener(target):
while True:
abs_file_path=yield
with open(abs_file_path,'rb') as f:
target.send((f,abs_file_path))

@init
def cat(target):
while True:
f,abs_file_path=yield
for line in f:
res=target.send((line,abs_file_path))
if res:
break


@init
def grep(pattern,target):
tag=False
pattern = pattern.encode('utf-8')
while True:
line,abs_file_path=yield tag
tag=False
if pattern in line:
target.send(abs_file_path)
tag=True


@init
def printer():
while True:
abs_file_path=yield
print(abs_file_path)

 


search(r'C:\Users\Administrator\PycharmProjects\19期\day4\a',opener(cat(grep('你好',printer()))))

三元表达式

name=input('>>: ')
if name == 'alex':
print('SB')
else:
print('NB')

name = input('>>: ')
print('SB' if name == 'alex' else 'NB')

def my_max(x,y):
return x if x > y else y

列表解析与生成器表达式

egg_list=[]
for i in range(10):
if i >= 3:
res='egg%s' %i
egg_list.append(res)

print(egg_list)


l=['egg%s' %i for i in range(10) if i >= 3]
print(l)

g=('egg%s' %i for i in range(10) if i >= 3)
print(next(g))

for i in ...:
if ...:
for i in ...:
if ...:
for ...


names=['egon','alex_sb','wupeiqi','yuanhao']

names=[name.upper() for name in names if not name.endswith('sb')]
print(names)
posted @ 2018-01-02 11:12  EiO  阅读(140)  评论(0)    收藏  举报
点我返回顶部