• Python3


    1.上节内容回顾                                                                                                                                             

    递归:

    • 明确的结束条件
    • 问题规模每递归一次都应该比上一次的问题规模有所减少
    • 效率低

    高阶函数

    文件:

    rb、wb、ab

    一般用在不同系统之间传数据,和传视频流的时候用到,一般以这种形式打开的需要制定encoding=‘utf-8’的字符编码形式

    其他:

    • f.seek()
    • f.tell()
    • f.truncate()
    • f.flush() 

    2.装饰器                                                                                                                                                     

     

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

    原则:

    • 不能修改被装饰的函数的源代码
    • 不能修改被装饰的函数的调用方式

    言外之意就是说被装饰的函数在装饰器前都是完全透明的

    实现装饰器知识储备:

    1. 函数即“变量”
    2. 高阶函数
        • 把一个函数名当做实参传给另外一个函数(不修改被装饰函数源代码的情况下为期添加功能)
        • 返回值中包含函数名(不修改函数的调用方式)

      3.嵌套函数

    一、函数的调用顺序:函数就像变量一样,在定义的时候就是把函数体赋值给函数名这样子,Python在调用函数之前,该函数一定要先被声明

    1 def foo():
    2     print(foo)
    3     bar()
    4 foo()
    5 def bar():
    6     print(bar)
    7 #报错,bar函数还未声明

     改正:

    1 def foo():
    2     print('foo')
    3     bar()
    4 def bar():
    5     print('bar')
    6 foo()
    二、 高阶函数
    1 def bar():
    2     print 'in the bar'
    3 def foo(func):
    4     res=func()
    5     return res
    6 foo(bar)

    三、嵌套函数

    1 def foo():
    2     def bar():
    3         print 'in the bar'
    4  
    5     bar()
    6  
    7 foo()

    四、装饰器

    装饰器的语法以@开头,接着就是装饰器要装饰的函数的声明

    装饰器就是一个函数,一个用来包装函数的函数,装饰器在函数声明完成的时候被调用,调用之后声明的函数被换成一个被装饰器装饰过后的函数。

    当函数有形参时,在装饰的函数中也需要有相应的形参;

    当原函数有return返回值时,在装饰的函数中也要萹蓄有return func(args);

    函数参数固定:

    1 def decorator(func):
    2     def wrapper(n):
    3         print('atarting')
    4         func(n)
    5         print('stopping')
    6     return wrapper
    7 def test(n):
    8     print('in the test arg is %s'%n)
    9 decorator(test)('alex')

    函数参数不固定

    1 def decorator(func):
    2     def wrapper(*args,**kwargs):
    3         print('starting')
    4         func(*args,**kwargs)
    5         print('stopping')
    6     return wrapper
    7 def test(n,x=1):
    8     print('in the test arg is %s,he is %d'%(n,x))
    9 decorator(test)('alex',x=2)

      1.无参装饰器

     1 import time
     2 def decorator(func):
     3     def wrapper(*args,**kwargs):
     4         start =time.time()
     5         func(*args,**kwargs)
     6         stop = time.time()
     7         print('run time is %s'%(stop-start))
     8     return wrapper
     9 @decorator  #test=decorator(test)
    10 def test(list_test):
    11     for i in list_test:
    12         time.sleep(0.1)
    13         print('_'*20,i)
    14 test(range(10))

      2.有参装饰器

     1 import time
     2 def timer(timeout =0):
     3     def decorator(func):
     4         def wrapper(*args,**kwargs):
     5             start = time.time()
     6             func(*args,**kwargs)
     7             stop = time.time()
     8             print("run time is %s"%(stop-start))
     9             print(timeout)
    10         return wrapper
    11     return decorator
    12 @timer(2)  #test=timer(2)(test)
    13 def test(list_test):
    14     for i in list_test:
    15         time.sleep(0.1)
    16         print('-'*20,i)
    17 test(range(10))

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

    举一个复杂的例子:

     1 import time
     2 user,passwd = 'alex','abc123'
     3 def auth(auth_type):
     4     print("auth func:",auth_type)
     5     def outer_wrapper(func):
     6         def wrapper(*args, **kwargs):
     7             print("wrapper func args:", *args, **kwargs)
     8             if auth_type == "local":
     9                 username = input("Username:").strip()
    10                 password = input("Password:").strip()
    11                 if user == username and passwd == password:
    12                     print("33[32;1mUser has passed authentication33[0m")
    13                     res = func(*args, **kwargs)  # from home
    14                     print("---after authenticaion ")
    15                     return res
    16                 else:
    17                     exit("33[31;1mInvalid username or password33[0m")
    18             elif auth_type == "ldap":
    19                 print("搞毛线ldap,不会。。。。")
    20 
    21         return wrapper
    22     return outer_wrapper
    23 
    24 def index():
    25     print("welcome to index page")
    26 @auth(auth_type="local") # home = wrapper()
    27 def home():
    28     print("welcome to home  page")
    29     return "from home"
    30 
    31 @auth(auth_type="ldap")
    32 def bbs():
    33     print("welcome to bbs  page")
    34 
    35 index()
    36 print(home()) #wrapper()
    37 bbs()
    View Code

     3.列表生成式,迭代器&生成器                                                                                                                                                   

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

    只记录当前的位置

    只有一个__next__()方法,next()

    列表生成式:

    需求:将列表[0,1,2,3,4,5,6,7,8,9]将列表里的每个值加1、

    三种写法:

    1 a =[0,1,2,3,4,5,6,7,8,9]
    2 b =[]
    3 for i in a:
    4     b.append(i+1)
    5 a =b
    6 print(a)
    第一种
    1 a = [1,2,3,4,5,6,7,8,9]
    2 a =map(lambda x:x+1,a) #map(f(x),列表名)
    3 for i in a:
    4     print(i)
    第二种
    1 a= [i+1 for i in range(10)]
    2 for i in a:
    3     print(i)
    第三种

    第三种即就是列表生成式

    生成器:

     通过列表生成式,我们可以直接创建一个列表,但是要创建100万个元素的列表,那么存储空间很庞大,因此,我们只需要生成式,它就是不必创建完整的list,从而节省大量空间,这种一遍循环一边计算的机制,称为生成器:generator

    创建generetor有以下几种方法:

    第一种:把列表生成式的[]改为(),就创建了一个generator

    1 >>> L = [x * x for x in range(10)]
    2 >>> L
    3 [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
    4 >>> g = (x * x for x in range(10))
    5 >>> g
    6 <generator object <genexpr> at 0x1022ef630>

     此时g已经是一个生成器

    如何一个个打印出来,用next()函数即可

     1 >>> next(g)
     2 0
     3 >>> next(g)
     4 1
     5 >>> next(g)
     6 4
     7 >>> next(g)
     8 9
     9 >>> next(g)
    10 16
    11 >>> next(g)
    12 25
    13 >>> next(g)
    14 36
    15 >>> next(g)
    16 49
    17 >>> next(g)
    18 64
    19 >>> next(g)
    20 81
    21 >>> next(g)
    22 Traceback (most recent call last):
    23   File "<stdin>", line 1, in <module>
    24 StopIteration
    View Code

    generator保存的是算法,每次调用next(),就计算出g的下一个元素的值,直到计算出最后一个元素,没有更多的元素时,跑出StopIteration错误

    不断调用next()方法太麻烦,因此用for循环,此种方法也不需要考虑StopIteration错误

     1 >>> g = (x * x for x in range(10))
     2 >>> for n in g:
     3 ...     print(n)
     4 ...
     5 0
     6 1
     7 4
     8 9
     9 16
    10 25
    11 36
    12 49
    13 64
    14 81
    View Code

     打印斐波拉契数列:

    斐波拉契数列(Fibonacci):1, 1, 2, 3, 5, 8, 13, 21, 34, ...

    1 def fib(max):
    2     n,a,b=0,0,1
    3     while n<max:
    4         print(b)
    5         a,b=b,a+b
    6         n =n+1
    7     return 'done'

     fib函数实际上定义了斐波拉契数列的推算规则,可以从第一个元素开始,推算出后续任意的元素,这种逻辑很类似generator。

    要把fib()变成generator,只需要把print(b)改为yield(b)即可

    1  def fib(max):
    2       n,a,b=0,0,1
    3       while n<max:
    4           #print(b)
    5           yield b   
    6           a,b=b,a+b
    7           n =n+1
    8       return ‘done' 
    >>> f = fib(6)
    >>> f
    <generator object fib at 0x104feaaa0>

    generator,在每次调用next()执行,遇到yield就返回,再次执行则从上次返回的yield语句处继续执行

    data = fib(10)
    print(data)
    
    print(data.__next__())
    print(data.__next__())
    print("干点别的事")
    print(data.__next__())
    print(data.__next__())
    print(data.__next__())
    print(data.__next__())
    print(data.__next__())
    
    #输出
    <generator object fib at 0x101be02b0>
    1
    1
    干点别的事
    2
    3
    5
    8
    13

    在循环过程中不断调用yield,就会不断中断,当然要给循环设置一个条件来退出循环,不然就会产生一个无限数列出来。

    把函数变成generator之后,基本不会用next()来获取下一个返回值,而是直接使用for循环来迭代:

    1 >>> for n in fib(6):
    2 ...     print(n)
    3 ...
    4 1
    5 1
    6 2
    7 3
    8 5
    9 8

    在用for循环调用generator时,发现拿不到generator的return语句的返回值,如果想要拿到返回值,必须捕获StopIteration错误,返回值包含在StopIteration的value中:

     1 >>> g = fib(6)
     2 >>> while True:
     3 ...     try:
     4 ...         x = next(g)
     5 ...         print('g:', x)
     6 ...     except StopIteration as e:
     7 ...         print('Generator return value:', e.value)
     8 ...         break
     9 ...
    10 g: 1
    11 g: 1
    12 g: 2
    13 g: 3
    14 g: 5
    15 g: 8
    16 Generator return value: done

    还可以使用yield实现单线程的情况下并发运算的效果

     1 #_*_coding:utf-8_*_
     2 __author__ = 'Alex Li'
     3 
     4 import time
     5 def consumer(name):
     6     print("%s 准备吃包子啦!" %name)
     7     while True:
     8        baozi = yield
     9 
    10        print("包子[%s]来了,被[%s]吃了!" %(baozi,name))
    11 
    12 
    13 def producer(name):
    14     c = consumer('A')
    15     c2 = consumer('B')
    16     c.__next__()
    17     c2.__next__()
    18     print("老子开始准备做包子啦!")
    19     for i in range(10):
    20         time.sleep(1)
    21         print("做了2个包子!")
    22         c.send(i)
    23         c2.send(i)
    24 
    25 producer("alex")
    26 
    27 #通过生成器实现协程并行运算

    迭代器:

    直接作用于for循环的数据类型以下几种:

    一类是集合数据类型:列表(list),元组(tuple),字典(dict),集合(set),字符串(str)等

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

    这类可直接作用于for循环的对象统称为可迭代对象:Tterable

    可以使用isinstance()判断一个对象是是否是Iterrator对象:

     1 >>> from collections import Iterable
     2 >>> isinstance([], Iterable)
     3 True
     4 >>> isinstance({}, Iterable)
     5 True
     6 >>> isinstance('abc', Iterable)
     7 True
     8 >>> isinstance((x for x in range(10)), Iterable)
     9 True
    10 >>> isinstance(100, Iterable)
    11 False

    而生成器不但可以作用于for循环,还可以被next()函数不断调用并但会下一个值,直到最后抛出StopIteration错误表示无法继续返回下一个值了。

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

    可以使用isinstance()判断一个对象是否是Iterator对象:

    1 >>> from collections import Iterator
    2 >>> isinstance((x for x in range(10)), Iterator)
    3 True
    4 >>> isinstance([], Iterator)
    5 False
    6 >>> isinstance({}, Iterator)
    7 False
    8 >>> isinstance('abc', Iterator)
    9 False

    由此可知:生成器都是Iterator对象,但列表、字典、字符串虽然是Iterable但不是Iterator

    小结:

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

    凡是可作用于next()函数的对象都是Iterator类型,他们表示一个惰性极端的序列(即只有在需要的时候才会计算,不需要则不会计算);

    集合数据类型如:列表、字典、字符串,集合等是Iterable但不是Iterator,不过可以通过iter()函数获得一个Iterator对象。

    如for新欢本质上是通过不断调用next()函数实现的:

     for x in [1, 2, 3, 4, 5]: pass 

    实际上等价于:

     1 # 首先获得Iterator对象:
     2 it = iter([1, 2, 3, 4, 5])
     3 # 循环:
     4 while True:
     5     try:
     6         # 获得下一个值:
     7         x = next(it)
     8     except StopIteration:
     9         # 遇到StopIteration就退出循环
    10         break

    4.内置函数                                                                                                                                                           

     见博客地址:

    5.软件目录结构规范                                                                                                                                               

     

  • 相关阅读:
    教你分分钟学会用python爬虫框架Scrapy爬取心目中的女神
    那些年,我们在Django web开发中踩过的坑(一)——神奇的‘/’与ajax+iframe上传
    刷题记录:[De1CTF 2019]Giftbox && Comment
    刷题记录:[强网杯 2019]Upload
    刷题记录:[XNUCA2019Qualifier]EasyPHP
    [RoarCTF 2019]simple_uplod
    [RoarCTF 2019]Online Proxy
    [RoarCTF]Easy Java
    [RoarCTF]Easy Calc
    刷题记录:[DDCTF 2019]homebrew event loop
  • 原文地址:https://www.cnblogs.com/gqq-0504/p/6204691.html
Copyright © 2020-2023  润新知