Python学习week4
Posted 我的下铺刚田武
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python学习week4相关的知识,希望对你有一定的参考价值。
装饰器:本质是函数,用来装饰其他的函数,为其它函数添加附加功能。
原则:不能改变被装饰函数的源代码和调用方式。
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 , 刚田武
以上是关于Python学习week4的主要内容,如果未能解决你的问题,请参考以下文章