博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
python第四周:装饰器、迭代器、内置方法、数据序列化
阅读量:5918 次
发布时间:2019-06-19

本文共 9273 字,大约阅读时间需要 30 分钟。

1.装饰器

定义:本质是一个函数,(装饰其他函数)就是为其他函数添加附加功能

原则:不能修改被装饰函数的源代码,不能修改被装饰函数的调用方式

实现装饰器的知识储备:

函数即“变量”。每当定义一个函数时,函数的名字就是变量的名字,函数体就是变量的内容

'''errordef foo():    print("in the foo")    bar()foo()''''''OKdef bar():    print("in the bar")def foo():    print("in the foo")    bar()foo()''''''OKdef foo():    print("in the foo")    bar()def bar():    print("in the bar")foo()''''''errordef foo():    print("in the foo")    bar()foo()def bar():    print("in the bar")'''

高阶函数:

a:把一个函数名当作实参传给另一个函数(在不修改被装饰函数源代码的情况下为其添加附加功能)

b:返回值中包含函数名(在不修改函数的调用方式)

import time'''把一个函数名当做实参传给另一个函数(在不修改被装饰函数源代码的情况下为其添加功能)def bar():    time.sleep(3)    print("in the bar")def test1(func):    start_time = time.time()    func()    stop_time = time.time()    print("the func run time is %s"%(stop_time-start_time))test1(bar)''''''返回值中包含函数名(不修改函数的调用方式)def bar():    time.sleep(0.1)    print("in the bar")def test2(func):    print(func)    return funcbar = test2(bar) #==》@test2bar()'''

嵌套函数:

嵌套函数+高阶函数=》装饰器

import  time#嵌套函数,在一个函数的函数体内定义另一个函数#被嵌套函数的作用域是嵌套它的函数的内部def foo():    print("in the foo")    def bar():        print("in the bar")    bar()foo()def auth(func):    def wrapper(*args,**kwargs):        start_time = time.time()        func(*args,**kwargs)        stop_time = time.time()        print("the func run time is %s"%(stop_time-start_time))    return wrapper@auth #相当于test=auth(test)-->test=wrapperdef test():    time.sleep(10)    print("in the tset")test()

装饰器完整程序示例:

测试时间

import  timedef timer(func): #timer(test1) func = test1    def deco():        start_time = time.time()        func() #func = test1        stop_time = time.time()        print("the func run time is %s"%(stop_time - start_time))    return deco@timer #test1=timer(test1)def test1():    time.sleep(3)    print("in the test1")@timer #test2=timer(test2)def test2():    time.sleep(2)    print("in the test2")#test1 = timer(test2)#test2 = timer(test2)test1()test2()

验证登陆

import  timeuser_name = "Mr Wu"user_passwd = "187847"def auth(auth_type):    print("by the %s"%auth_type)    def out_wrapper(func):        def wrapper(*args,**kwargs):            if auth_type == "local":                name = input("input your usernmae:")                passworld = input("input your passworld:")                if name == user_name and passworld == user_passwd:                    func(*args,**kwargs)                else:                    exit("invalid input!")            elif auth_type == "ldt":                print("老子不会!操!")        return wrapper    return out_wrapper@auth(auth_type="local")#相当于@out_wrapper-->home = out_wrapper(home)-->home = wrapperdef home():    print("welcome to home page!")@auth(auth_type="ldt")def bbs():    print("welcome to bbs page!")home()bbs()

2.迭代器与生成器

生成器:

列表生成式:通过列表生成式,我们可以直接创建一个列表,但是受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅需要很大的存储空间,如果我们仅仅需要访问前面的几个元素,那后面绝大多数元素占用的空间都白白浪费了。

生成器:所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环过程中不断推算出后续元素呢,这样就不必创建完整的list,从而节省大量的空间。在python中,这种一边循环一边计算的机制i,称为生成器:generator

创建一个generator的两种方法:

(1)只要把一个列表生成式的[]改为(),就创建了一个generator。只有在调用时才会生成相应的数据,只能记住当前的位置,只有一个_next_()方法。

(2)带有yield的generator function(生成器函数)

#第一种生成器方法==》通过列表生成式改造counting = (i for i in range(100))for i in counting:    print(i)#第二种成器方法==》通过函数生成def counting(max):    n = 0    while n

迭代器:

可以被next()函数调用并不断返回下一个值,直到没有数据时抛出StopIteration错误的对象称为迭代器:Iterator

可以直接作用域for循环的数据类型有以下几种:
(1)集合数据类型,如list、tuple、dict、set、str

(2)generator,包括生成器和带yield的generator function

这些可以直接作用于for循环的对象称为可迭代对象:Iterable,可以使用isinstance()判断一个对象是否是Iterable对象

生成器(generator)都是Iterator对象,但是list、dict、str虽然是Iterable,却不是Iterator。把list、dict、str变成Iterator可以使用iter()函数

为什么list、dict、str等数据类型不是Iterator?

这是因为python的Iterator表示的是一个数据流(没有一个确定的结束值)。Iterator的对象可以被next()函数调用,直到抛出Stopiteration错误。可以把这个数据看做是一个有序序列,但我们却不能知道序列的长度,只能通过next()函数实现按需计算下一个数据,所以Iterator的计算时惰性的,只有在需要返回下一个数据时才会进行计算。Iterator甚至可以表示一个无限大的数据流,例如全体自然数,而使用list是永远不可能存储全体自然数的

程序示例:

python中的for循环本质上就是通过不断调用next()函数实现的:

for i in [1,2,3,4,5]:    print(i)#完全等价于以下程序:it = iter([1,2,3,4,5])while True:    try:        #获得下一个值        x = next(it)    except StopIteration:        #遇到StopIteration就退出循环        break

通过yield实现在单线程的情况下实现并发运算的效果

#吃包子--做包子--》生产--消费流程import timedef consumer(name):    print("%s 准备吃包子啦!"%name)    while True:        baozi = yield        print("包子[%s]来了,被[%s]吃了!"%(baozi,name))#c = consumer("alex")#c.__next__()#b1 = "韭菜馅"#c.send(b1) #调用生成器,同时给yield传值def producer(name):    c = consumer("A")    c2 = consumer("B")    c.__next__()    c2.__next__()    print("老子开始准备做包子啦!")    for i in range(10):        time.sleep(0.5)        print("做了两个包子!")        c.send(i)        c2.send(i)producer("alex")

3.内置方法

print(all([0,-5,3])) #如果Iterable内部元素都为真,返回True,否则返回Falseprint(any([0,-4,5])) #如果Iterable内部有一个元素为真,返回True,否则(Iterable为空)返回Falsea = ascii([1,2,"开外挂"]) #把列表变成了一个字符串print(type(a),[a]) #
["[1, 2, '\\u5f00\\u5916\\u6302']"]print(bin(1)) #将数字转换为二进制print(bool(0)) #判断真假 True、Falsea = bytes("abcde",encoding="utf-8")#字节print(a.capitalize(),a) #b'Abcde' b'abcde'b = bytearray("abcde",encoding="utf-8")#字节数组print(b) #bytearray(b'abcde')b[1] = 50print(b) #bytearray(b'a2cde')print(callable([])) #判断是否可以调用print(chr(98)) #将ASCII码转换为字符print(ord("a")) #将字符转换为ASCII码print(divmod(5,2)) #返回商和余数(2, 1)#filter:对每个值进行过滤后返回结果形成列表rest = filter(lambda n:n<5,range(10))for i in rest: print(i)#map:对每个值进行处理后返回结果形成列表res = map(lambda n:n*n,range(10))for i in res: print(i)import functoolsres = functools.reduce(lambda x,y:x*y,range(1,10))#阶乘print(res)a = frozenset([1,2,3,4,5,6,3,3,3,3])#不可变集合print(a)print(globals())#把当前文件下的所有变量及其方法取出来形成一个字典print(hash("alex")) #将字符串映射成数字(哈希)#help("time") #查看模块的帮助文档print(hex(123)) #将一个数字转换为十六进制print(len("abc123"))#返回字符串的长度def test(): local_var = 333 print(locals())test() #locals()打印局部变量print(globals().get("local_var")) #error,globals()打印全局变量print(max([1,2,3,4,5])) #返回列表中的最大值print(min([1,2,3,4,5])) #返回列表中的最小值print(oct(10)) #将一个数字转为八进制print(pow(3,4)) #计算某个数字的多少次幂print(round(1.4321,4)) #保留多少位小数a = {6:2,8:0,1:4,-5:6,99:11,4:22}#print(sorted(a.items()))#排序print(sorted(a.items(),key = lambda x:x[1]))a = [1,2,3,4,5]b = ["a","b","c","d"]for i in zip(a,b): print(i) #(1, 'a') #(2, 'b') #(3, 'c') #(4, 'd')__import__("decorator1")

compile、eval、exec、single

#compile(source, filename, mode, flags=0, dont_inherit=False, optimize=-1)'''说明:  1. 将source编译为代码或者AST对象。代码对象能够通过exec语句来执行或者eval()进行求值。  2. 参数source:字符串或者AST(Abstract Syntax Trees)对象。即需要动态执行的代码段。  3. 参数 filename:代码文件名称,如果不是从文件读取代码则传递一些可辨认的值。当传入了source参数时,filename参数传入空字符即可。  4. 参数mode:指定编译代码的种类,可以指定为 ‘exec’,’eval’,’single’。当source中包含流程语句时,mode应指定为‘exec’;        当source中只包含一个简单的求值表达式,mode应指定为‘eval’;当source中包含了交互式命令语句,mode应指定为'single'。   5.当一个字符串被exec,eval(),或execfile()执行时,解释器会先将它们编译为字节代码,然后再执行.这个过程比较耗时,      所以如果需要对某段代码执行很多次时,最好还是对该代码先进行预编译,这样就不需要每次都编译一遍代码,可以有效提高程序的执行效率。'''#exec:当source中包含流程语句时,mode应指定为‘exec’code1 = "for i in range(10):print(i)"compile1 = compile(code1,'','exec')exec(compile1)#eval:当source中只包含一个简单的求值表达式,mode应指定为‘eval’code2 = "3 + 5 -6*7"compile2 = compile(code2,'','eval')print(eval(compile2))#single:当source中包含了交互式命令语句,mode应指定为'single'code3 = 'name = input()'compile3 = compile(code3,'','single')exec(compile3)print(name)

4.json和pickle数据序列化

 json序列化:把内存中的数据和对象存到硬盘中(文件只能写进字符串)

注:json序列化只支持最简单的数据类型,像函数这种不能序列化

序列化:

import jsoninfo = {    "name":"alex",    "age":22,}f = open("test.txt","w",encoding="utf-8")f.write(json.dumps(info))f.close()'''def sayhi(name):    print("hello,",name)info = {    "name":"alex",    "age":22,    "func":sayhi}f = open("test2","w",encoding="utf-8")f.write(json.dumps(info)) #error, 
is not JSON serializablef.close()'''
#dump一次就load一次,不能多次load;每dump一次就生成一个新的文件,再load一次import jsoninfo = {    "name":"alex",    "age":22,}f = open("test.txt","w",encoding="utf-8")f.write(json.dumps(info))info["age"] = 20f.write(json.dumps(info))data = json.loads(f.read())#errorf.close()

反序列化:

import jsonf = open("test.txt","r",encoding="utf-8")data = json.loads(f.read())#data = json.load(f)print(data)f.close()

5.软件目录规范

软件结构规范:为什么要设计好目录结构   “设计目录结构”就和“代码编写风格”一样,属于个人风格问题。    设计一个层次清晰的目录结构,就是为了达到以下两点:       1.可读性高:不熟悉这个项目的代码的人,一眼就能看懂目录结构,知道程序启动脚本是哪个,测试目录在哪儿,配置文件在哪儿等等         从而快速的了解这个项目       2.可维护性高:定义好组织规则后,维护者就能很明确的知道,新增的哪个文件和代码应该放在什么目录之下。这个好处是随着时间的推移,         代码/配置的规模增加,项目结构不会混乱,仍然能组织良好    因此保持一个层次清晰的目录结构是有必要的。更何况组织一个良好的工程目录,其实是一个很简单的事儿目录组织方式:    关于如何组织一个较好的python工程目录结构,已经有一些得到了共识的目录结构。在StackOverflow的这个问题上,    能看到大家对python目录结构的讨论。    假设你的项目名为foo,我比较建议的最方便快捷目录结构这样就足够了:    Foo/    |-- bin/    | |-- foo    |    |-- foo/    | |-- test/    | | |-- _init_.py    | | |-- test_main.py    | |    | |-- _init_.py    | |-- main.py    |    |-- docs/    | |-- conf.py    | |-- abc.rst    |    |-- setup.py    |-- requirements.txt    |-- README    简单解释一下:    1.bin/:存放项目的一些可执行文件,当然你可以起名script/之类的也行    2.foo/:存放项目的所有源代码。(1)源代码中的所有模块、包都应该放在此目录,不要置于顶层目录。                               (2)其子目录tests/存放单元测试代码                               (3)程序的入口最好命名为main.py    3.docs/:存放一些文档。    4.setup.py:安装、部署、打包的脚本。    5.requirements.txt:存放软件依赖的外部python包列表    6.README:项目说明文件,目的是能简单描述该项目的信息,让读者快速了解这个项目      它需要说明一下几个事项:          1.软件定位,软件的基本功能          2.运行代码的方法:安装环境、启动命令          3.简要的使用说明          4.代码目录结构说明,更详细点可以说明软件的基本原理。          5.常见问题说明

转载于:https://www.cnblogs.com/BUPT-MrWu/p/9734441.html

你可能感兴趣的文章
Android NetWorkUtil
查看>>
如何在 Linux 上录制你的终端操作
查看>>
JAVA基础培训(isoft)
查看>>
Atitit.基于时间戳的农历日历历法日期计算
查看>>
Windows消息目录
查看>>
BZOJ3145 : [Feyat cup 1.5]Str
查看>>
Linux命令-sudo
查看>>
【USACO 1.3】Barn Repair
查看>>
Java 并发
查看>>
开学了!这些Linux认证你要知道
查看>>
Substance 6 设置 watermark(水印)
查看>>
php中Closure::bind用法(手册记录)
查看>>
chrome使用技巧(看了定不让你失望)
查看>>
Gulp真实项目用例
查看>>
sql练习(针对Mysql)
查看>>
再玩 DevStack(Mitaka版)- 基于 trystack.cn 源
查看>>
你用过Spring中哪些功能?
查看>>
『翻译』为什么.Net CF在调用HTTPS 的Web服务时失败?!
查看>>
PriorityQueue的Java实现
查看>>
PHP 跟老大的对话
查看>>