python学习笔记(三)

 

目录:python

1、装饰器算法

2、迭代器与生成器json

3、内置方法详解flask

4、Json与pickle数据序列化api

5、软件目录结构规范app

 

1、装饰器ssh

  定义:装饰器自己是函数,(装饰其余函数),就是为其余函数添加附加功能。函数

  原则:1.不能修改被装饰函数的源代码单元测试

           2.不能修改被装饰函数的调用方式测试

  装饰器应用详解

    实现装饰器的知识储备:

      1.函数即“变量”

      2.高阶函数

      3.嵌套函数

      高阶函数+嵌套函数-->装饰器

  

__Author__ = 'Redleafage Zhang'

import time

def timmer(func): #装饰器
    def warpper(*args,**kwargs):
        start_time = time.time()
        func()
        stop_time = time.time()
        print('the func run time is %s' %(stop_time-start_time))
    return warpper

@timmer
def test1():
    time.sleep(3) #运行逻辑所花费的时间
    print('in the test1')

test1()

    打印结果:

      

 

    1.装饰器之“函数即变量“

      匿名函数:

calc = lambda x:x*3 #匿名函数,没有名字的函数
print(calc(3)) #返回9

        变量名至关于门牌号,存放的内容至关于房间里的东西(占内存空间),函数名也至关于门牌号,函数体(函数的具体内容)在房间里面。以下图:

          

 

    2.高阶函数:

     a.把一个函数名看成实参传给另一个函数(在不修改被装饰函数源代码的状况下为其添加功能)

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

      

def bar():
    print("in the bar!")
def test1(func):
    print(func)
    func() 能够运行

test1(bar) #打印内存地址,bar只表明标示函数体的门牌号
func = bar
func() #能够运行,传递地址,至关于x=1,y=x

      打印结果:

      

 

def bar():
    time.sleep(3)
    print('in the bar')


def test2(func):
    print(func)
    return func

#print(test2(bar)) #两次都打印地址
bar = test2(bar) #覆盖以前的bar函数,至关于test2加上了新功能,函数调用方式没有改变,python解释器有专门的符号可解释此过程,后面讲
bar() # run bar

      打印结果:

        

 

import  time
def bar():
     time.sleep(3)
     print('in the bar')
def test1(func):
     start_time = time.time()

     func() #run bar
     stop_time = time.time()
     print('the func run time is %s' % (stop_time-start_time) )

test1(bar)

        打印结果:

          

 

 

 

    3.嵌套函数

      

def foo(): #函数的嵌套,嵌套指在函数内部以def形式定义新函数
    print('in the foo')
    def bar(): #局部变量
        print('in the bar')

    bar()
foo()
def test1(): #这叫函数的调用,不是嵌套。
    test2()
test1()

      局部做用域与全局做用域的访问顺序

    

x=0
def grandpa():
    #x=1
    def dad():
        x=2
        def son():
            x=3
            print(x)
        son()
    dad()
grandpa() #结果返回3

    实例:

__Author__ = 'Redleafage Zhang'
import time
def timer(func):
    def deco(*args,**kwargs): #是否传递参数都无所谓了
        start_time = time.time()
        func(*args,**kwargs) #run test1
        stop_time = time.time()
        print('the func run time is %s' %(stop_time-start_time))
    return deco

# def timer():
#     def deco():
#         pass

@timer #至关于test1 = timer(test1)
def test1():
    time.sleep(3)
    print('in the test1')
@timer #test2 = timer(test2)= deco test2() = deco()
def test2(name,age):

    print('test2',name,age)

#print(timer(test1)) #打印内存地址
#test1 = timer(test1)
#test1()  #-->deco
test1()
test2('linda',22)

      打印结果:

        

 

      终极实例:

__Author__ = 'Redleafage Zhang'

import time
user,passwd = 'alex','abc123'
def auth(auth_type):
    print("auth func:",auth_type)
    def outer_wrapper(func):
        def wrapper(*args, **kwargs):
            print("wrapper func args:", func)
            if auth_type == 'local':
                username = input("Username:").strip()
                password = input("Password:").strip()

                if user == username and passwd == password:
                    print("\033[32;1mUser has passed authentication\033[0m")
                    res = func(*args, **kwargs)
                    print("---after authentication")
                    return res

                else:
                    exit("\033[31;1mInvalid username or password\033[0m")
            elif auth_type == '1dap':
                print("搞毛线1dap,不会。。。")


        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 = '1dap')
def bbs():
    print('welcome to bbs page')
index()
print(home()) #wrapper()
bbs()

      打印结果:

      

 

 

2、迭代器与生成器

  列表生成式:

    

[i*2 for i in range(10)] #生成[0,2,4,6,8,10,12,14,16,18]

  生成器:

    经过列表生成式,咱们能够直接建立一个列表。可是,收到内存限制,列表容量确定是有限的。并且,建立一个包含100万个元素的列表,不只占用很大的存储空间,若是咱们仅仅须要访问

  前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。

    因此,若是列表元素能够按照某种算法推算出来,那咱们是否能够在循环的过程当中不断推算出后续的元素呢?这样就能够没必要建立完整的list,从而节省大量的空间,在python中,这种一边

  循环一边计算的机制,称为生成器:generator。

    要建立一个generator,有不少种方法。第一种方法很简单,只要把一个列表生成式的[]改为(),就建立了一个generator

    

    1.生成器只有在调用时才会生成相应的数据

    2.调用生成器下一个数据:__next__()

      

 

     3.生成器只记录当前位置,只有一个next方法它不知道前面和后面,前面用完了就没了,不能往回调用。每次只保留一个值。

 

    generator很是强大, 若是推算的算法比较复杂,用相似列表生成式的for循环没法实现的时候,还能够用函数来实现。

    好比,著名的斐波那契数列(Fibonacci),除第一个和第二个数外,任意一个数均可以由前两个数相加获得:

    1,1,2,3,5,8,13,21,34,……

    斐波那契数列用列表生成式写不出来,可是,用函数把它打印出来却很容易:

    

def fib(max):
    n,a,b = 0,0,1
    while n < max:
        print(b)
        a,b = b,a+b
        n = n+1
    return 'done'

    注意,赋值语句:

a,b = b,a+b

    至关于  

t = (b,a+b) #t是一个tuple
a = t[0]
b = t[1]

    而不是至关于

a=b 
a=1
b=2
a=b
a=2
b=a+b
b=2+2 = 4

    仔细观察,能够看出,fib函数其实是定义了斐波那契数列的推算规则,能够从第一个元素开始,推算出后续任意的元素,这种逻辑其实很是相似generator

    也就是说,上面的函数和generator仅一步之遥。要把fib函数变成generator,只须要把print(b)改成yield b就能够了:

  

def fib(max):
    n,a,b = 0,0,1
    while n < max:
        #print(b)
        yield b
        a,b = a,a+b
        n += 1
    return 'done'

    调用生成器:

    

print(fib(10)) #返回地址
f = fib(10)
print(f.__next__())
print(f.__next__())
print(f.__next__())

    打印结果:

    

 

     实例:

__Author__ = 'Redleafage Zhang'
import time
def consumer(name):
    print("%s 准备吃包子啦!" %name)
    while True:
       baozi = yield #None,由于是生成器,返回值后再也不执行,再次输入__next__()才会继续执行

       print("包子[%s]来了,被[%s]吃了!" %(baozi,name))

c = consumer("ChenRonghua")
c.__next__()

# b1= "韭菜馅"
# c.send(b1) #把b1发送过去,被yield接收到
# c.__next__()

def producer(name):
    c = consumer('A') #这一步只是把c变成生成器,不执行内容,next后才会开始执行
    c2 = consumer('B')
    c.__next__()
    c2.__next__()
    print("老子开始准备作包子啦!")
    for i in range(10):
        time.sleep(1)
        print("作了1个包子,分两半!")
        c.send(i)
        c2.send(i)

producer("alex")

    打印结果:

    

    迭代器

      咱们已经知道,能够直接做用于for循环的数据类型有如下几种:

      一类是集合数据类型,如list,tuple,dict,set,str等;

      一类是generator,包括生成器和带yield的generator function.

      这些能够直接做用于for循环的对象统称为可迭代对象:Iterable.

      可使用isinstance()判断一个对象是不是Iterable对象:

        

 

        能够被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator.

        

 

 

         生成器确定是迭代器,迭代器不必定是生成器。

        

 

         生成器都是Iterator对象,但list,dict,str虽然是Iterable,却不是Iterator

         把list,dict,str等Iterable变成Iterator可使用iter()函数:

        

 

 

         你可能会问,为何list,dict,str等数据类型不是Iterator?

         这是由于Python的Iterator对象表示的是一个数据流,Iterator对象能够被next()函数调用并不断返回下一个数据,直到没有数据时抛出StopIteration错误,能够把这个数据流看做是

        一个有序序列,但咱们却不能提早知道数列的长度,只能不断经过next()函数实现按需计算下一个数据,因此Iterator的计算是惰性的,只有在须要返回下一个数据时它才会计算。

      

        Iterator甚至能够表示一个无限大的数据流,例如全体天然数。而使用 list 是永远不可能存储全体天然数的。(惰性计算:走到这一步再算,没走到就不算)

        凡是可用于for循环的对象都是Iterable类型:

        凡是可做用于 next()函数的对象都是Iterator类型,它们表示一个惰性计算的序列:

        集合数据类型如list,dict,str等是Iterable但不是Iterator,不过能够经过iter()函数得到一个Iterator对象。

 

3、内置方法详解

  全部内置方法:

    

 

  哈希:

    

    若是直接搜索中文集,效率低,若是有500万个数据,则须要循环500万次,把无序的中文集经过映射转换为数字,并排序,查找的时候用折半查找的方式找对应的数字,提升效率。python

    的字典是用哈希的方法实现的。MD5也属于哈希

 

    内置函数详解:

    

__Author__ = 'Redleafage Zhang'

print(all([0,-5,3])) #若是可迭代对象里全部的元素都为真(或者是空值),则返回真
print(any([0,-5.3]))#可迭代数据里任意的数据为真,则为真,若是是空的,则返回假
a=ascii([1,2,'开外挂了']) #把内容转换成字符串
print(type(a),[a])
print(bin(9)) #十进制转二进制
print(bool(1)) #判断真假

a=bytes("abcde",encoding="utf-8")
b = bytearray("abcde",encoding="utf-8")
print(b[0]) #打印ASCII码
b[1] = 100 #不能赋值字符串,只能赋ASCII码形式
# print(a)
# print(a.capitalize(),a) 变大写,不改变原字符串
print(callable([])) #判断是否可调用,能加括号的可调用(好比函数),列表返回False
print(chr(88)) #把数字对应ASCII码字符打印出来
print(ord('a')) #把字符转为ASCII码
code = "for i in range(10):print(i)"
c = compile(code,'','exec')#exec表示能够把字符串之造成代码
exec(c)
code = "1+3/2*6"
#c = compile(code,'','eval') #eval计算数字
#eval(c) #CMD里可运行
eval(code) #CMD里可运行,把字符串变成字典

code = '''
def fib(max):
    n,a,b = 0,0,1
    while n < max:
        #print(b)
        yield b
        a,b = b,a+b
        n = n+1
    return 'done' #此时fib已是一个生成器,而不是一个函数,所以return是在异常测试时打印出来的东西,而不是函数的返回值

print(fib(10))
f = fib(10)
print(f.__next__())
print(f.__next__())
print(f.__next__())
'''

py_obj = compile(code,"err.log",'exec')
exec(py_obj)
exec(code) #直接用exec也能够,compile没什么用
a = {}
print(dir(a)) #查参数有什么方法能够用

print(divmod(5,2)) #相除并返回商和余数,归为元祖

def sayhi(n): #若是这个函数只使用一次,用def占用空间
    print(n)
    for i in range(n): #此种lambda没法模拟
        print(i)

sayhi(3)

#匿名函数,用完就释放,不占空间
print((lambda n:print(n))(5)) #(5)为传参
calc = lambda n:print(n)
calc(5) #效果同上
calc = lambda  n:3 if n<4 else n
calc(5)

res=filter(lambda n:n>5,range(10))#把大于5的过滤掉,返回迭代器
res = map(lambda n:n*2,range(10))#对传入的每一个值按逗号前的方法得出结果 [i*2 for i in range(10)]
for i in res:
    print(i)

res = [lambda i:i*2 for i in range(10)]#效果同上

import functools
res = functools.reduce(lambda x,y:x+y,range(10)) #从1加到9,x+y的值返回x ,y为range(10)的下一个值
print(res)

a = frozenset([1,4,333,212,33,33,12,4]) #不可变集合,不可增删
print(globals()) #返回当前整个程序全部变量的keyvalue的格式,变量名是key,变量名对应的值是value

print(hash('alex')) #把字符变成映射的数字

print(hex(122)) #把数字转成16进制

def test():
    local_var = 333
    print(locals()) #打印当前函数全部的局部变量,以字典的形式
    print(globals()) #打印结果无局部变量
test()
print(globals().get('local_var')) #没法取到函数里的值,global只打印全局变量,不打印局部变量
print(oct(10)) #转八进制
print(pow(3,5)) #3的5次方
round(1.3342,2) #保留两位小数
slice(2,5,None)
d = range(10)
d[slice(2,5)] #至关于d[2:5],没什么用

a = {6:2,8:0,1:4,-5:6,99:11,4:22}
print(sorted(a.items())) #把无序的字典按key排序
print(sorted(a.items(),key = lambda x:x[1])) #把无序的字典按value排序
print(a) #无序

a = [1,2,3,4]
b = ['a','b','c','d']
for i in zip(a,b): #拼两个列表,返回元组
    print(i)


__import__('decorator')  #之后会用到

    打印结果:

/Library/Frameworks/Python.framework/Versions/3.6/bin/python3.6 /Users/zhangshu/PycharmProjects/s14/day4/内置方法.py
False
True
<class 'str'> ["[1, 2, '\\u5f00\\u5916\\u6302\\u4e86']"]
0b1001
True
97
False
X
97
0
1
2
3
4
5
6
7
8
9
<generator object fib at 0x10410d200>
1
1
2
<generator object fib at 0x10410d2b0>
1
1
2
['__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'clear', 'copy', 'fromkeys', 'get', 'items', 'keys', 'pop', 'popitem', 'setdefault', 'update', 'values']
(2, 1)
3
0
1
2
5
None
5
0
2
4
6
8
10
12
14
16
18
45
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x101eb85c0>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': '/Users/zhangshu/PycharmProjects/s14/day4/内置方法.py', '__cached__': None, '__Author__': 'Redleafage Zhang', 'a': frozenset({1, 33, 4, 12, 333, 212}), 'b': bytearray(b'adcde'), 'code': "\ndef fib(max):\n    n,a,b = 0,0,1\n    while n < max:\n        #print(b)\n        yield b\n        a,b = b,a+b\n        n = n+1\n    return 'done' #此时fib已是一个生成器,而不是一个函数,所以return是在异常测试时打印出来的东西,而不是函数的返回值\n\nprint(fib(10))\nf = fib(10)\nprint(f.__next__())\nprint(f.__next__())\nprint(f.__next__())\n", 'c': <code object <module> at 0x1040f5a50, file "", line 1>, 'i': 18, 'py_obj': <code object <module> at 0x1040f5b70, file "err.log", line 2>, 'fib': <function fib at 0x104108598>, 'f': <generator object fib at 0x10410d2b0>, 'sayhi': <function sayhi at 0x101e62ea0>, 'calc': <function <lambda> at 0x104108ae8>, 'res': 45, 'functools': <module 'functools' from '/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/functools.py'>}
-652459854530933945
0x7a
{'local_var': 333}
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x101eb85c0>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': '/Users/zhangshu/PycharmProjects/s14/day4/内置方法.py', '__cached__': None, '__Author__': 'Redleafage Zhang', 'a': frozenset({1, 33, 4, 12, 333, 212}), 'b': bytearray(b'adcde'), 'code': "\ndef fib(max):\n    n,a,b = 0,0,1\n    while n < max:\n        #print(b)\n        yield b\n        a,b = b,a+b\n        n = n+1\n    return 'done' #此时fib已是一个生成器,而不是一个函数,所以return是在异常测试时打印出来的东西,而不是函数的返回值\n\nprint(fib(10))\nf = fib(10)\nprint(f.__next__())\nprint(f.__next__())\nprint(f.__next__())\n", 'c': <code object <module> at 0x1040f5a50, file "", line 1>, 'i': 18, 'py_obj': <code object <module> at 0x1040f5b70, file "err.log", line 2>, 'fib': <function fib at 0x104108598>, 'f': <generator object fib at 0x10410d2b0>, 'sayhi': <function sayhi at 0x101e62ea0>, 'calc': <function <lambda> at 0x104108ae8>, 'res': 45, 'functools': <module 'functools' from '/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/functools.py'>, 'test': <function test at 0x104108bf8>}
None
0o12
243
[(-5, 6), (1, 4), (4, 22), (6, 2), (8, 0), (99, 11)]
[(8, 0), (6, 2), (1, 4), (-5, 6), (99, 11), (4, 22)]
{6: 2, 8: 0, 1: 4, -5: 6, 99: 11, 4: 22}
(1, 'a')
(2, 'b')
(3, 'c')
(4, 'd')
in the test1
the func run time is 3.002807140350342

Process finished with exit code 0

 

 

4、Jason与pickle数据序列化

  Json:多语言可用,只能存放简单数据

  Pickle:只有python能用,能存放复杂数据(如函数)

import json
info = {
      'name':'alex',
      'age':22
 }
f = open('test.text','w')
print(json.dumps(info))
f.write(json.dumps(info)) #直接以字典格式存入文件
f = open('test.text','r')
data = json.loads(f.read()) #恢复数据
print(data['age'])

  打印结果:

    

  pickle:

    

import pickle
def sayhi(name):
    print("hello",name)
info = {
      'name':'alex',
      'age':22,
      'func':sayhi #pickel能够存储函数,而json不行
}
f = open("test.text",''wb")
print(pickle.dumps(info))
f.write(pickle.dumps(info)) #直接以字典格式存入文件
f = open("test.text","rb")
data = pickle.loads(f.read()) #恢复数据
print(data)

    打印结果:

    

 

    注:pickle.dump(info,f) 等同于f.write(pickle,dumps(info)) 

      data = pickle.load(f) 等同于pickle.loads(f.read())

      写程序时每dump一次,就要loadi 次,不要一次dump不少行,宁肯dump成好几个文件。

5、软件目录结构规范

  

  1.bin/: 存放项目的一些可执行文件,固然你能够起名script/之类的也行。

  2.foo/:存放项目的全部源代码。(1)源代码中的全部模块、包都应该放在此目录。不要只置于顶层目录。(2)其子目录test/存放单元测试代码;(2)程序的入口最好命名为main.py

  3.docs/:存放一些文档

  4.setup.py:安装、部署、打包的脚本

  5.requirements.txt:存放软件依赖的外部Python包列表

  6.README:项目说明文件

  除此以外,有一些方案给出了更多的内容。好比ICENSE.txt,ChangeLog.txt文件等,通常开源的时候会用到。

  关于README的内容:

    这个是每一个项目都应该有的一个文件,目的是要能简要描述该项目的信息,让读者快速了解这个项目。

    它须要说明如下几个事项:

      1.软件定位,软件的基本功能。

      2.运行代码的方法:安装环境、启动命令等。

      3.简要的使用说明。

      4.代码目录结构说明,更详细点能够说明软件的基本原理。

      5.常见问题说明。

  requirements.txt:

  这个文件存在的目的是:

    1.方便开发者维护软件的包依赖。将开发过程当中新增的包添加进这个列表中,避免在setup.py安装依赖时漏掉软件包。

    2.方便读者明确项目使用了哪些Python包。

  这个文件的格式是每一行包含一个包依赖的说明。一般是flask >= 0.10这种格式,要求是这个格式能被pip识别,这样就能够简单的经过pip install -r requirements.txt来把全部的python包依赖

  都安装好了。

  

  注意:从foo调main须要跨目录

    经过os方法找到主目录,添加给环境变量,再导入其它模块便可。

    

相关文章
相关标签/搜索