zoukankan      html  css  js  c++  java
  • 容器、迭代器、生成器,闭包,装饰器,作用域,动态添加属性和方法

    '''
    容器是一系列元素的集合,str、list、set、dict、file、sockets对象都可以看作是容器,容器都可以被迭代(用在for,while等语句中),因此他们被称为可迭代对象。
    可迭代对象实现了__iter__方法,该方法返回一个迭代器对象。
    迭代器持有一个内部状态的字段,用于记录下次迭代返回值,它实现了__next__和__iter__方法,迭代器不会一次性把所有元素加载到内存,而是需要的时候才生成返回结果。
    生成器是一种特殊的迭代器,它的返回值不是通过return而是用yield。
    '''
    '''判断是否可以迭代'''
    from collections import Iterable
    print(isinstance("abc",Iterable))
    print(isinstance(100,Iterable))


    '''闭包'''
    print('-----------1-----------------------')
    def line_conf(a,b):
    def line(x):
    return a*x + b
    return line
    line1 = line_conf(1,1)
    line2 = line_conf(4,5)
    print(line1(5))
    print(line1(6)) #闭包的作用就是在下次用同样的参数a、b时,函数会自动保存参数a、b,只需输入参数x即可。
    print(line2(5))
    print(line1(7))


    '''装饰器'''
    print('-----------2-----------------------')
    def w1(func):
    def inner():
    print('---正在验证权限----')
    if True:
    func()
    else:
    print('---验证不通过---')
    return inner

    @w1
    def f1():
    print('---f1---')

    @w1
    def f2():
    print('---f2---')

    f1()
    f2()


    '''两个装饰器'''
    print('-----------3-----------------------')
    #定义函数:完成包裹数据
    def makeBold(fn):
    def wrapped():
    print('------1-------')
    return "<b>" + fn() + "</b>"
    return wrapped

    #定义函数:完成字体斜体
    def makeItalic(fn):
    def wrapped():
    print('-----2------')
    return "<i>" + fn() + "</i>"
    return wrapped

    #装饰器在代码执行到改行时候,已经开始装饰了,而非下边的调用test3()时候才开始装饰,即在调用test3()时候已经装饰好了。
    @makeBold
    @makeItalic
    def test3():
    print('-----3------')
    return "hello world-3"

    ret = test3() #先执行makeBold装饰器,装饰器中的wrapped函数中遇到函数fn()就会向下执行,
    # 由于下边是makeItalic装饰器,则将makeItalic赋值给该fn(),同理makeItalic中的fn()将被赋值予test3(),依次调用执行。
    print(ret)



    '''有参函数装饰器'''
    print('-----------4-----------------------')
    def func(functionName):
    print('---func---1---')
    def func_in(*args,**kwargs): #如果a,b没有定义,那么会导致99行的调用失败
    print('---func_in---1---')
    functionName(*args,**kwargs) #如果没有把a,b当做实参进行传递,那么会导致调用92行的函数失败
    print('---func_in---2---')

    print('---func---2---')
    return func_in

    @func
    def test(a,b,c):
    print('---------test-a=%d,b=%d,c=%d---------'%(a,b,c))

    @func
    def test2(a,b,c,d):
    print('------test2-a=%d,b=%d,c=%d,d=%d-----'%(a,b,c,d))

    test(11,22,33)
    test2(11,22,33,44)


    '''装饰器对带有返回值的函数进行装饰'''
    print('-----------5-----------------------')
    def func16(functionName):
    print('-----func----1-----')
    def func_in():
    '''如果这样写,127行会得不到值。
    因为在执行test16()时,会先执行他的装饰器,装饰器中return func_in,则找到func_in()函数,
    此函数中执行了装饰器装饰的函数,则去调用test16(),func_in()函数执行完并没有返回值,所以127行得不到返回值。
    print('---func_in---1----')
    functionName()
    print('---func_in---2----')
    '''
    print('---func_in---1----')
    ret16 = functionName() #保存返回来的haha
    print('---func_in---2----')
    return ret16 #把haha返回到128行处的调用

    print('-----func----2-----')
    return func_in

    @func16
    def test16():
    print('------test16-----')
    return "haha"

    ret16 = test16()
    print('test return value is %s'%ret16)


    '''通用装饰器:无论装饰函数是否有参数,是否有返回值,该装饰器都适用。'''
    print('-----------6-----------------------')
    def func40(functionName):
    def func_in(*args,**kwargs):
    ret = functionName(*args,**kwargs)
    return ret
    return func_in

    @func40
    def test40():
    print('----test40----')

    @func40
    def test41():
    print('----test41-----')
    return "hahahaha"

    @func40
    def test42(a):
    print('-----test42------a=%d--'%a)

    ret40 = test40()
    print('test40 return value is %s'%ret40)

    ret41 = test41()
    print('test41 return value is %s'%ret41)

    ret42 = test42(111)
    print('test42 return value is %s'%ret42)



    '''带有参数的装饰器'''
    print('-----------7-----------------------')
    def func_arg(arg):
    def func(functionName):
    def func_in():
    print('---记录日志-arg=%s---'%arg)
    if arg=="heihei":
    functionName()
    functionName()
    else:
    functionName()
    return func_in
    return func

    @func_arg("heihei") #带有参数的装饰器,能够起到在运行时,有不同的功能。
    def test34():
    print('----test34----')

    @func_arg("haha")
    def test35():
    print("----test35----")

    test34()
    test35()


    '''作用域'''
    print(globals()) #全局变量
    print(locals()) #局部变量
    print('-----------8-----------------------')
    #LEGB规则:Python使用LEGB的顺序来查找一个符号对应的对象。
    # locals->enclosing function(外部嵌套函数的命名空间,闭包中常见)->globals->builtins(内建模块的命名空间)


    '''python动态添加属性以及方法'''
    #动态语言:可以在运行的过程中,修改代码
    #静态语言:编译时已经确定好代码,运行过程中不能修改
    print('-----------9-----------------------')
    class Person():
    def __init__(self,newName):
    self.name = newName

    def eat(self):
    print("-----%s正在吃-------"%self.name)

    def run(self):
    print("-----%s正在跑-------"%self.name)

    laowang = Person("老王")
    print(laowang.name)
    laowang.addr = "北京..."
    print(laowang.addr)

    laozhao = Person("老赵")
    # print(laozhao.addr) 此处报错,因为laozhao这个实例对象还没有添加addr这个属性

    Person.num = 100 #给类添加属性
    print(laowang.num)
    print(laozhao.num)

    p1 = Person("p1")
    p1.eat()
    p1.run = run
    # p1.run() #虽然p1对象中run属性已经指向了207行的函数,,,到那时这句代码还不正确
    #因为run属性指向的函数是后来添加的,即p1.run()的时候,并没有把p1当做第一个参数self,
    #导致了第207行的函数调用的时候,出现缺少参数的问题。

    import types
    p1.run = types.MethodType(run,p1) #给对象添加实例方法的正确方式
    p1.run()

    @staticmethod #静态方法装饰器
    def ttest():
    print('---------static method----------')

    Person.ttest = ttest #静态方法、类方法是跟着类走的
    Person.ttest()

    @classmethod #静态方法装饰器
    def printNumm(cls):
    print('------class method--------')

    Person.printNumm = printNumm
    Person.printNumm()

    class Personn():
    __slots__ = ("name","age") #定义类的时候定义一个特殊的_slots_变量,来限制该class实例能添加的属性。
    #_slots_定义的属性仅对当前类实例起作用,对类和继承的子类是不起作用的。

    pp = Personn()
    pp.name = "老王"
    pp.age = 20
    # pp.score = 60 类实例在添加属性时候,非_slots_变量元组中的属性不能添加,类在添加时可以随意添加属性。
    Personn.score = 80 #可以添加类的属性

    #互换两个数字
    a = 9
    b = 4
    a,b = b,a
    print(str(a),str(b))


    '''生成器:一边循环一边计算的机制,成为生成器。保存了计算值的算法,并没有执行,而是什么时候调用这个值什么时候执行。'''
    print('-----------10-----------------------')
    # alist = [x*2 for x in range(100000000000)] #直接生成,会内存错误
    #①第一种方式实现生成器
    blist = (x*2 for x in range(100000000000)) #什么时候用什么时候生成
    print(next(blist))
    print(next(blist))

    #②第二种方式实现生成器
    def creatNum():
    print("-----start-----")
    a,b = 0,1
    for i in range(5):
    print('----1----')
    yield b #yield作用:暂停程序,将yield后的值返回
    print('-----2------')
    a,b = b,a + b
    print('----3-----')
    print('------stop------')

    #创建了一个生成器
    scq = creatNum()
    print(next(scq)) #next(scq):让scq这个生成器对象开始执行,如果是第一次执行,那么就从creatNum的开始部分执行,
    #如果是之前已经执行过了,那么就从上一次停止的位置开始执行。
    print(scq.__next__()) #next(scq)和scq.__next__()作用一样

    print('-----')
    for num in scq:
    print(num)


    #send("haha"):作用类似于next(),不同的是send会将"haha"赋值给yeild b的整体结果。
    print('-----------10-----------------------')
    def test28():
    i = 0
    while i<5:
    temp = yield i
    print(temp)
    i += 1

    t28 = test28()
    print(t28.__next__())
    print(t28.__next__())
    print(t28.send("haha")) #从上一次暂停的地方开始执行,即yield i处开始执行,将"haha的值赋值给yield i整体的结果即temp,所以执行print(temp)输出haha。"

    #切换多个任务一起执行:协程,协程比进程和线程要快。
    def ttest1():
    while True:
    print('--1--')
    yield None

    def ttest2():
    while True:
    print('--2--')
    yield None

    tt1 = ttest1()
    tt2 = ttest2()
    while True:
    tt1.__next__()
    tt2.__next__()

  • 相关阅读:
    灰度发布
    rabbitmq应用场景
    redis设置cpu核数与内存
    使用word2010发布博客到博客园
    讲师
    UML-6.3-用例-详述示例
    UML-6.2-用例-用例模型/用例/场景关系
    UML-6.1-用例-示例
    数据库增量同步开源软件
    UML-5-进化式需求
  • 原文地址:https://www.cnblogs.com/wisir/p/10097581.html
Copyright © 2011-2022 走看看