装饰器:本质是函数,用来装饰其他的函数,为其它函数添加附加功能。
原则:不能改变被装饰函数的源代码和调用方式。
1、函数即‘变量’,定义一个函数相当于把函数体赋值给函数名,匿名函数相当于只有函数体没有函数名
def func1():
print('in the function')
func2=func1 #和普通的整数赋值一样:a=2 b=a print(b)
func2()
2、高阶函数
3、嵌套函数
装饰器=高阶函数+嵌套函数
高阶函数:
1、把一个函数名当作实参传递给另外一个函数;(在不修改被装饰函数源代码的情况下为其添加功能)
2、返回值中包含函数名。(不修改函数的调用方式)

import time
def bar():
time.sleep(2)
print('in the bar')
def timer(func):
start_time=time.time()
func()
stop_time=time.time()
print('the time of running is %s'%(stop_time-start_time))
timer(bar)
输出:
in the bar
the time of running is 2.0002079010009766

import time
def bar():
time.sleep(2)
print('in the bar')
def test(func):
print(func) #如果参数是函数,则此处打印的是函数在内存中的位置信息
func()
return func
test(bar) #将函数名作为实参传递给调用函数
#test(bar()) #错误用法,将函数返回值传递给调用函数,不符合高阶函数定义
输出:
<function bar at 0x000001717B027F28>
in the bar
嵌套函数:在一个函数的函数体内定义另一个函数,不是调用,是def定义

def test():
print('in the test')
def inner(): #内部函数,相当于局部变量,只能在test()内部调用
print('in the inner')
inner()
test()
输出:
in the test
in the inner
装饰器:

import time
def timer(func): #嵌套函数
def decorator(*args):
start_time=time.time()
func(*args)
stop_time=time.time()
print('the running time of this function is %s'%(stop_time-start_time))
return decorator #返回函数名,不能带有括号
@timer #相当于test=timer(test),timer(test)返回decorator()函数。
def test1():
time.sleep(2)
print('in the test1')
@timer
def test2(name,age):
print('in the test2:', name, age)
test1()
test2('刚田武',22)
输出:
in the test1
the running time of this function is 2.000319242477417
in the test2: 刚田武 22
the running time of this function is 0.0

username,password='zhhy','123'
def auth(auth_type):
print('auth type:',auth_type)
def outer_wrapper(func):
def wrapper(*args, **kwargs):
print('wrapper args:',*args,**kwargs)
if auth_type == 'local':
user_name = input('please input your name:').strip()
pass_word = input('please input your password:').strip()
if username == user_name and password == pass_word:
print('\033[32;1mUser pass authentication\033[0m ')
result = func(*args, **kwargs)
print('after authentication')
return result
else:
exit('\033[32;1mInvalid username or password\033[0m ')
elif auth_type=='ldap':
print('using ldap')
return wrapper
return outer_wrapper
def index():
print('welcome to index page')
@auth(auth_type='local')
def home():
print('welcome to home page')
return 'from home'
@auth(auth_type='ldap')
def bbs():
print('welcome to bbs page')
home()
列表生成式:生成列表的简便方法。
print([i*2 for i in range(10)]) 输出: [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
i*2可以换成func()。
生成器:generator=(i*2 for i in range(10))
1、数据较多并且有规律时,可以减少内存占用,要调用的数据才会产生;
2、不支持切片操作;
3、只有__next__()方法;
4、只保存当前调用数据。

generator=(i*2 for i in range(10)) print(generator.__next__()) print(generator.__next__()) 输出: 0 2
斐波那契数列:
def fib(max):
n,a,b=0,0,1
while n<max:
a,b=b,a+b
n+=1
return b
print(fib(10))
其中,a,b=b,a+b相当于:
tuple=(b,a+b) a=tuple[0] b=tuple[1]
改为生成器:yield b
def fib():
a,b=0,1
while True:
yield b
a,b=b,a+b
f=fib()
print(f.__next__())
含有yield的函数称为生成器,生成器的return语句和函数的不同,其return的值赋给异常StopIteration,用try可以捕获异常,避免程序出错。
如果一个函数定义中包含yield关键字,那么这个函数就不再是一个普通函数,而是一个generator;
函数是顺序执行,遇到return语句或者最后一行函数语句就返回。而变成generator的函数,在每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行;
用for循环调用generator时,发现拿不到generator的return语句的返回值。如果想要拿到返回值,必须捕获StopIteration错误,返回值包含在StopIteration的value中。
def fib(max):
n,a,b=0,0,1
while n<max:
yield b
a,b=b,a+b
n+=1
return '---------done---------'
f=fib(5)
while True:
try:
# x=next(f)
# print('f:',x)
print(f.__next__())
except StopIteration as e:
print('生成器返回值:',e.value)
break
输出:
1
1
2
3
5
生成器返回值: ---------done---------
yield可以在单线程环境中进行类似并行计算,称为协程。
import time
def consumer(name): #不断吃包子
print('[%s]来吃包子,'%name)
while True:
baozi=yield #baozi的值由send()方法传来
print('[%s]包子被[%s]吃了'%(baozi,name))
def producer(name):
a=consumer('刚田武') #consumer是生成器,不会执行
b=consumer('胖虎')
a.__next__() #调用next()后才会执行,consumer运行到baozi=yield处退出此生成器,等待send()方法传值。
b.__next__()
print('[%s]开始做包子'%name)
for i in range(5):
time.sleep(2)
print("做了2个包子")
a.send('白菜馅') #send()传值给baozi后,a运行print('[%s]包子被[%s]吃了'%(baozi,name)),然后循环运行到baozi=yield跳出
b.send('番茄馅')
producer("朱二娃")
输出:
[刚田武]来吃包子,
[胖虎]来吃包子,
[朱二娃]开始做包子
做了2个包子
[白菜馅]包子被[刚田武]吃了
[番茄馅]包子被[胖虎]吃了
迭代器:
可以直接作用于for循环的数据类型有以下几种:一类是集合数据类型,如list、tuple、dict、set、str等;一类是generator,包括生成器和带yield的generator function。
这些可以直接作用于for循环的对象统称为可迭代对象:Iterable。
而生成器不但可以作用于for循环,还可以被next()函数不断调用并返回下一个值,直到最后抛出StopIteration错误表示无法继续返回下一个值了。
可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator。
生成器都是Iterator对象,但list、dict、str虽然是Iterable,却不是Iterator,可以通过。[http://www.cnblogs.com/alex3714/articles/5765046.html]iter()函数获得一个Iterator对象
from collections import Iterator from collections import Iterable print(isinstance([],Iterator)) #列表不是迭代器对象,返回False print(isinstance([],Iterable)) #列表是可迭代对象,返回True print(isinstance(iter([]),Iterator)) #iter()后的列表是可迭代对象,返回True 输出: False True True
json序列化和反序列化:可以把内存中的数据存储到硬盘中,便于下次从硬盘中读取数据,相当于把程序暂停。
只能进行简单的数据类型序列化,可以在不同编程语言或者程序之间交互数据。

import json
info={"name":"刚田武",'age':20}
f=open('test.text','w')
print(json.dumps(info))
f.write(json.dumps(info))

import json
f=open('test.text','r')
data=json.loads(f.read())
print(data['name'])
pickle和json类似,优点是可以序列化所有数据类型,包括函数。序列化函数时,反序列化只能得到函数名,没有函数体,需要把函数体复制到反序列化中。可以更改函数体。

import pickle
def hello(name):
print('hello,',name)
info={'name':'刚田武','age':20,'func':hello}
f=open('test.text','wb')
f.write(pickle.dumps(info)) #pickle.dump(info,f)效果相同

import pickle
def hello(name):
print('hello,',name)
f=open('test.text','rb')
data=pickle.loads(f.read()) #data=pickle.load(f)
data['func']('刚田武')
软件目录结构规范:层次清晰的目录结构规范有助于提高程序的可读性和可维护性。
Foo/ |-- bin/ | |-- foo | |-- foo/ | |-- tests/ | | |-- __init__.py | | |-- test_main.py | | | |-- __init__.py | |-- main.py | |-- docs/ | |-- conf.py | |-- abc.rst | |-- setup.py |-- requirements.txt |-- README
简要解释一下:
bin/: 存放项目的一些可执行文件,当然你可以起名script/之类的也行。foo/: 存放项目的所有源代码。(1) 源代码中的所有模块、包都应该放在此目录。不要置于顶层目录。(2) 其子目录tests/存放单元测试代码; (3) 程序的入口最好命名为main.py。docs/: 存放一些文档。setup.py: 安装、部署、打包的脚本。requirements.txt: 存放软件依赖的外部Python包列表。README: 项目说明文件。[https://www.cnblogs.com/alex3714/articles/5765046.html]
从atm文件夹下的atm.py文件中调用core文件夹下的main.py的方法:
import os,sys
BASE_DIR=os.path.dirname(os.path.dirname(os.path.abspath(__file__))) #找到程序的根目录
sys.path.append(BASE_DIR) #添加环境变量,BASE_DIR是当前程序的根目录,便于调用其他文件夹下的程序文件。
from core import main
from conf import setting
main.login('刚田武')
其中main.py为:
def login(name):
print('welcome to atm ,',name)
输出为:
welcome to atm , 刚田武
来源:https://www.cnblogs.com/zhhy236400/p/9670829.html
