函数
*args:接收溢出位置参数; 将位置参数存成一个元组的形式
**kwargs:接收溢出的关键字参数; 将关键字函数存成一个字典的形式
一、装饰器
故名思议就是装饰函数用的
二、函数对象:函数可被当做数据传输
- 函数可以当做传递给另一个函数
- 一个函数的返回值也可以是一个函数
三、名称空间与作用域
名称空间分为三种
内置名称空间:Python解释器启动则生效
全局名称空间:执行Python文件生效
全局名称空间:调用函数时临时生效,调用结束的时候失效。
- 加在顺序:先内置函数,在全局,最后有可能产生句部
- 查找名字的顺序:先局部,在全局,最后内置
作用分两种
全局作用域:全局存活,全局有效
句部作用域:临时存活,句部有效
四、装饰器
闭包函数:定义在函数内部的函数,特点是:包含对外部作用域而不是全局作用域名字的引用,就称之为闭包函数。
x = 1
def outter():
x = 2
def inner():
print(x)
return inner
f=outter()
#这里相当于将inner():函数以变量的形式传递给outter()这个函数所以print()打印的是outter中的x = 2
为什么要用装饰器:开放封闭原则,对扩展是开放的,对修改是封闭的
什么事是装饰器:
- 用来装饰它人,装饰器本身可以是任意可调用对象,被装饰对象也可以是任意可调用对象。
- 遵循的原则:
1、不修改被装饰对象的源代码
2、不修改被装饰对象的调用方式
- 目标:在循环原则1和2的前提,被装饰器对象添加上新功能
用闭包实现装饰器
import time
def index():
time.sleep(3)
print("welcome index")
def timmer(func):
#func = index #最原始的index函数的内存地址
def inner():
start_time=time.time()
index()
stop_time=time.time()
print("run time is :[%s]"%(stop_time-start_time))
return inner
index=timmer(index)
index()
#我们将index函数产地给timmer函数,通过return将inner函数的内容传递给timmer第一层下,这是func为index函数,然后执行。
例:这就是一个装饰器
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 #这里就是将index的内置属性全都给inner
def timmer(func):
@wraps(func)
def inner(*args,**kwargs):
start_time=time.time()
res=func(*args,**kwargs) #这里是返回源index的返回值
stop_time=time.time()
print('run time is :[%s]' %(stop_time-start_time))
return res #这里就是返后index的返回值
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(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()
五、迭代器
1、什么是迭代器:迭代器是一个重复过程,每次重复都是基于上一次的结果来的
2、为什么要用迭代器:对于序列类型:字符串、列表、元组,可以使用基于索引的迭代取值方式;对于没有索引的方式如:字典、集合、文件,这种方式不再适合,于是我们必须超出一种不能依赖于索引的方式;
3、可迭代的对象:只要对象内置有__iter__方法,obj.iter
可迭代对象:字符串、列表、元组、集合、字典、文件。
4、迭代器对象:对象即内置有__iter__方法,有内置有__next__
可迭代对象:文件
注意可迭代对象不一定是迭代器对象,而迭代器对象一定是可迭代对象。迭代器对象自身也有__iter__方法,但是迭代器对象在__iter__就是自己本身。
dic={"a":1,"b":2}
iter_dic = dic.__iter__()
iter_dic.__next__
#通过__iter__()既可以把可迭代对象,转换成得迭代器。
dic={"a":1,"b":2}
iter_dic = dic.__iter__()
iter_dic.__next__
print(iter_dic.__next__())
print(iter_dic.__next__())
#print(next(iter_dic))
#也可以用next方法来取值;但是超出取值范围,报错。
#处理方法异常处理
dic={"a":1,"b":2}
iter_dic = dic.__iter__()
while True:
try:
print(next(iter_dic))
except StopIteration:
break
for循环就是依赖这种机制,所以for循环不依赖索引。for循环是调用__iter__()方法来实现。 把它变成迭代器对象。
总结:
迭代器的优缺点:
- 优点:
提供了一种统一的迭代取值方法,该方法不在依赖于索引;
更节省内存;
- 缺点:
不可逆的,一次性,无法获取指定位置的值;
无法统计长度;
扩展:
form cllections import iterable,iterator
#可以通过这两种方法判断是不是可迭代对象。iterable可迭代去对象,iterator迭代器
六、生成器
定义:只要函数内部出现yield关键字,那么在调用该函数,将不再会立即执行函数整体代码,会得到一个结果,该结果就是生成器对象。
生成器本质就是迭代器(iter)
def func():
print("==========>1")
yield 1
print("==========>2")
yield 2
print("==========>3")
yield 3
g = func()
next(g)
next(g)
next(g)
G:\python3\pythonw3.exe H:/Python项目/草稿/迭代器.py
==========>1
==========>2
==========>3
#注意,如果超出生成器本身个数,会报错。
yield的功能:
- 为我们提供一个种自定义的迭代器的方式
- 对比return,可以返回多个值,挂起函数的执行状态
用迭代器模拟range函数
def my_range(start,stop,step=1): #开始,结束,步长
while start < stop:
yield start
start += step
g=my_range(1,5)
print(next(g))
print(next(g))
print(next(g))
print(next(g))
G:\python3\pythonw3.exe H:/Python项目/草稿/迭代器.py
1
2
3
4
#这里需要注意,当迭代数等于5时候,报错。这也是根据range函数特性。
def eater(name):
print("%s 开动了"%name)
while True:
food = yield #第一次就是为了初始化停到yield位置
print("%s 开始吃了 %s"%(name,food))
g = eater("tom")
print(g.send(None))
g.send("骨头")
G:\python3\pythonw3.exe H:/Python项目/草稿/迭代器.py
tom 开动了
None
tom 开始吃了 骨头
#这里需要注意一下,g.end(None)第一次一定要传一个None。才能传递其他值
#send()有两个功能,其中一个就是想next()一样,另一个传值并返回给food.
七、面向过程编程
面向过程编程绝对不是用函数编程那么简单。
面向过程的编程思想:核心是过程二字,过程即解决问题的步骤,即先干了什么,基于该思想去编写程序就好比在设计一条流水线。是一种机械式的编程思想。
优点:将复杂的问题流程化,进而简单化;
缺点:可扩展性差;
#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()))))
八、三元表达式
针对简单的if判断
判断成功的结果在左边,失败的在右边。判断在中间
name = input(">>: ")
"tom is boy" if name == "tom" else: "is not tom"
九、列表解析与生成器表达式
l = ["egg%s" %i for i in range(10)]
print(l)
G:\python3\pythonw3.exe H:/Python项目/草稿/day3.py
['egg0', 'egg1', 'egg2', 'egg3', 'egg4', 'egg5', 'egg6', 'egg7', 'egg8', 'egg9']
#列表解析就是针对for循环说的
l = ["egg%s" %i for i in range(10) if i > 4]
#这里就是先处理for循环后边的事,然后在赋值给前边的egg
#那么它的完整语法是这样的
for i in ...:
if ...:
#从if后边还能加
#for i in ...:
# if ...:
#如果用()就是生成器可以用next去取值
十、序列化
什么是序列化
把对象(变量)从内存中编程可存储或传输的过程就称之为序列化,在Python中叫pickling,在其他语言中也被称之为serialization,marshalling,flattening等等,都是一个意思。
为什么要序列化
1、保持持久化状态
当计算机断电或者重启之前将当前内存中的所有数据保存下来,一边下次程序执行能给从文件中读取载入数据。例如虚拟机快照。
2、跨平台数据交换
打破平台和语言差异带来的限制,实现了跨平台数据交互。
json和pickle
json表示的对象就是标准的javascript语言的对象,JSON和Python内置的数据类型对应如下:
过程内存中的结构化的数据---------->格式json------------>字符串----------------->保存到文件或者基于网络传输
import json
dic={'name':'alvin','age':23,'sex':'male'}
print(type(dic))#<class 'dict'>
j=json.dumps(dic)
print(type(j))#<class 'str'>
f=open('序列化对象','w')
f.write(j) #-------------------等价于json.dump(dic,f)
f.close()
#-----------------------------反序列化<br>
import json
f=open('序列化对象')
data=json.loads(f.read())# 等价于data=json.load(f)
#注意
import json
#dct="{'1':111}"#json 不认单引号
#dct=str({"1":111})#报错,因为生成的数据还是单引号:{'one': 1}
dct='{"1":"111"}'
print(json.loads(dct))
#conclusion:
#无论数据是怎样创建的,只要满足json格式,就可以json.loads出来,不一定非要dumps的数据才能loads 注意点
pickle
过程
内存中的结构化的数据----------------->格式pickle------------------->bytes类型-------------->保存到文件或者基于网络传输
import pickle
dic={'name':'alvin','age':23,'sex':'male'}
print(type(dic))#<class 'dict'>
j=pickle.dumps(dic)
print(type(j))#<class 'bytes'>
f=open('序列化对象_pickle','wb')#注意是w是写入str,wb是写入bytes,j是'bytes'
f.write(j) #-------------------等价于pickle.dump(dic,f)
f.close()
#-------------------------反序列化
import pickle
f=open('序列化对象_pickle','rb')
data=pickle.loads(f.read())# 等价于data=pickle.load(f)
print(data['age'])
#需要注意:pickle只能用于Python

浙公网安备 33010602011771号