python第四周学习内容

Posted bupt-mrwu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python第四周学习内容相关的知识,希望对你有一定的参考价值。

1.装饰器

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

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

实现装饰器的知识储备:

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

‘‘‘
error
def foo():
    print("in the foo")
    bar()
foo()
‘‘‘‘‘‘
OK
def bar():
    print("in the bar")
def foo():
    print("in the foo")
    bar()
foo()
‘‘‘‘‘‘
OK
def foo():
    print("in the foo")
    bar()
def bar():
    print("in the bar")
foo()
‘‘‘‘‘‘
error
def 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 func
bar = test2(bar) #==》@test2
bar()‘‘‘

嵌套函数:

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

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=wrapper
def test():
    time.sleep(10)
    print("in the tset")
test()

装饰器完整程序示例:

测试时间

import  time
def 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  time
user_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 = wrapper
def 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<max:
        yield n
        n += 1
count = counting(100)
print(count.__next__())
print("My name is Mr Wu")
print(count.__next__())
print("I am a man")
print(count.__next__())
print("I am 19 years old")
print(count.__next__())
print("I like Python")
print(count.__next__())
print("I like C")
for i in count:
    print(i)

迭代器:

可以被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 time
def 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,否则返回False
print(any([0,-4,5])) #如果Iterable内部有一个元素为真,返回True,否则(Iterable为空)返回False
a = ascii([1,2,"开外挂"]) #把列表变成了一个字符串
print(type(a),[a]) #<class ‘str‘> ["[1, 2, ‘\u5f00\u5916\u6302‘]"]
print(bin(1)) #将数字转换为二进制
print(bool(0)) #判断真假 True、False
a = 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] = 50
print(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 functools
res = 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 json
info = {
    "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, <function sayhi at 0x0000012217F211E0> is not JSON serializable
f.close()
‘‘‘
#dump一次就load一次,不能多次load;每dump一次就生成一个新的文件,再load一次
import json
info = {
    "name":"alex",
    "age":22,
}
f = open("test.txt","w",encoding="utf-8")
f.write(json.dumps(info))
info["age"] = 20
f.write(json.dumps(info))
data = json.loads(f.read())#error
f.close()

反序列化:

import json
f = 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.常见问题说明






以上是关于python第四周学习内容的主要内容,如果未能解决你的问题,请参考以下文章

Python学习第四周总结

第四周学习总结

第四周学习总结

Python学习笔记第二十四周(JavaScript补充)

Python 学习日记(第四周)

20165234 第四周学习总结