资讯专栏INFORMATION COLUMN

Python_装饰器和生成器

sugarmo / 2718人阅读

摘要:迭代器迭代是访问集合元素的一种方式。迭代器是一个可以记住遍历的位置的对象,迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束,迭代器只往前不会往后退。生成器特点保存了一套生成数值的算法。

迭代器

迭代是访问集合元素的一种方式。
迭代器是一个可以记住遍历的位置的对象,迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束,迭代器只往前不会往后退。

可迭代对象

以直接作用域for循环的数据类型:

集合数据类型:list, tuple, dict, set, str

generator,包括生成器yieldgenerator function

判断是否可以迭代

使用方法isinstance()判断一个对象是否具有Iterable对象

from collections import Iterable

isinstance("abc", Iterable) # true
迭代器

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

生成器, tuple

from collections import Iterator

isinstance((x for x in range(10)), Iterator) # True
isinstance([], Iterator) # False 列表不是迭代对象

iter()函数
生成器都是Iterator对象, 但是list, dict, str虽然是Iterable,却不是Iterator

可以把其他类型转成生成器, 使用iter()函数

闭包

函数是引用

闭包:

def test(number):
    def test_in(number_in):
        print(number_in)
        return number + number_in
    return test_in

test(10)(20)
装饰器

对函数或方法起装饰作用

写代码要遵循开放封闭原则。
它规定已经实现的功能代码不允许被修改,但可以被扩展。

封闭: 已实现的功能代码块
开放: 对扩展开发

装饰器原理:

def a(func):
    def inner():
        func()
    return inner()
    
def f1():
    print("f1")

f1 = a(f1) # 函数名作为变量名,重新赋值使用
f1()

装饰器语法糖:

def a(func):
    def inner():
        func()
    return inner()

@a
def f1():
    print("f1")

f1()         
二个装饰器
def makeBold(fn):
    def warpped():
        print("1")
        return "" + fn() + ""
    return warpped

def makeItalic(fn):
    def warpped():
        print("2")
        return "" + fn() + ""
    return warpped

@makeBold
@makeItalic
def test1():
    print("3")
    return "hello world"

ret = test1()
print(ret)

# 输出结果:
# 1
# 2
# 3
# hello world    
装饰器执行的时间
def w1(func):
    print("1")
    def inner():
        print("2")
        func()
    return inner

def w2(func):
    print("4")
    def inner():
        print("5")
        func()
    return inner

@w2
@w1
def f1():
    print(3)

# 执行f1
f1()
# 1 2 3 # 只有w1 装饰
# 1 4 5 2 3 # w1,w2共同装饰

# 不执行f1
# 1 4
装饰器对有参数、无参数函数进行装饰
def func(funName):
    print("1")
    def func_in(argA, argB): # 形参
        print("2")
        funName(argA, argB) # 调用传递参数
    return func_in


@func
def test(a, b):    
    print("a=%d,b=%d"%(a,b))

test(10, 20)

*args来解决多参数问题

def func(funName):
    print("1")
    def func_in(*args, **kwargs): # 形参
        print("2")
        funName(*args, **kwargs) # 调用传递参数
    return func_in


@func
def test(a, b):    
    print("a=%d,b=%d"%(a,b))

test(10, 20)
装饰器对带有返回值的函数进行装饰
def func(funName):
    print("1")
    def func_in():
        print("2")
        return funName() # 返回值
    return func_in


@func
def test():    
    return "test"

ret = test()
print(ret)
通用装饰器
def func(funName):
    def func_in(*args, **kwargs):
        return funName(*args, **kwargs) # 返回值
    return func_in


@func
def test():    
    return "test"

ret = test()
print(ret)
带有参数装饰器
from time import ctime, sleep

def timefun_arg(pre="hello"):
    def timefun(func):
        def warppedfunc():
            print("%s called at %s %s"%(func.__name__, ctime(), pre))
            return func()
        return warppedfunc
    return timefun


@timefun_arg("it") # 执行,主动调用。需要多一层闭包函数
def foo():
    print("foo")

@timefun_arg("python")
def too():
    print("too")

foo()
sleep(2)
too()
作用域
globals

查看命名空间中所有全局变量:
globals()以字典方式返回

{"__name__": "__main__", "__doc__": None, "__package__": None, "__loader__": , "__spec__": None, "__annotations__": {}, "__builtins__": }
locals

查看命名空间中局部变量
locals()以字典方式返回:

{"__name__": "__main__", "__doc__": None, "__package__": None, "__loader__": , "__spec__": None, "__annotations__": {}, "__builtins__": }
LEGB规则

Python使用LEGB的顺序来查找一个符号对应的对象

locals -> enclosing function -> globals -> builtins

locals: 当前所在的命名空间(如函数,模块),函数的参数也属于命名空间内的变量
enclosing: 外部嵌套函数的命名空间
globals: 全局变量,函数定义所在模块的命名空间
builtins: 内建模块的命名空间

查看内建模块的变量:dir(__builtins__)

["ArithmeticError", "AssertionError", "AttributeError", "BaseException", "BlockingIOError", "BrokenPipeError", "BufferError", "BytesWarning", "ChildProcessError", "ConnectionAbortedError", "ConnectionError", "ConnectionRefusedError", "ConnectionResetError", "DeprecationWarning", "EOFError", "Ellipsis", "EnvironmentError", "Exception", "False", "FileExistsError", "FileNotFoundError", "FloatingPointError", "FutureWarning", "GeneratorExit", "IOError", "ImportError", "ImportWarning", "IndentationError", "IndexError", "InterruptedError", "IsADirectoryError", "KeyError", "KeyboardInterrupt", "LookupError", "MemoryError", "ModuleNotFoundError", "NameError", "None", "NotADirectoryError", "NotImplemented", "NotImplementedError", "OSError", "OverflowError", "PendingDeprecationWarning", "PermissionError", "ProcessLookupError", "RecursionError", "ReferenceError", "ResourceWarning", "RuntimeError", "RuntimeWarning", "StopAsyncIteration", "StopIteration", "SyntaxError", "SyntaxWarning", "SystemError", "SystemExit", "TabError", "TimeoutError", "True", "TypeError", "UnboundLocalError", "UnicodeDecodeError", "UnicodeEncodeError", "UnicodeError", "UnicodeTranslateError", "UnicodeWarning", "UserWarning", "ValueError", "Warning", "WindowsError", "ZeroDivisionError", "_", "__build_class__", "__debug__", "__doc__", "__import__", "__loader__", "__name__", "__package__", "__spec__", "abs", "all", "any", "ascii", "bin", "bool", "bytearray", "bytes", "callable", "chr", "classmethod", "compile", "complex", "copyright", "credits", "delattr", "dict", "dir", "divmod", "enumerate", "eval", "exec", "exit", "filter", "float", "format", "frozenset", "getattr", "globals", "hasattr", "hash", "help", "hex", "id", "input", "int", "isinstance", "issubclass", "iter", "len", "license", "list", "locals", "map", "max", "memoryview", "min", "next", "object", "oct", "open", "ord", "pow", "print", "property", "quit", "range", "repr", "reversed", "round", "set", "setattr", "slice", "sorted", "staticmethod", "str", "sum", "super", "tuple", "type", "vars", "zip"]
动态绑定

动态绑定属性:

class Person(object):
    def __init__(self):
        pass
        
p1 = Person
p1.name = "pp" # 动态添加属性

print(p1.name)

动态绑定方法:

import types
class Person(object):
        def __init__(self, newName, newAge):
                self.name = newName
                self.age = newAge
        def eat(self):
                print("eat-", self.name)

def run(self):
        print("run-", self.name)

p1 = Person("p1", 24)
p1.eat()

# 通过types库中的MethodType方法来修改指向函数中的this指针
p1.run = types.MethodType(run, p1) # 动态添加方法

p1.run()

绑定静态方法和静态属性:

class Person(object):
    def __init__(self):
        pass



@staticmethod
def test():
    print("static method")

Person.test = test # 绑定静态方法
Person.name = "alogy" # 绑定静态属性

Person.test()

绑定类属性:

class Person(object):
    def __init__(self):
        pass


@classmethod
def printNum(cls):
    print("class method")

Person.printNum = printNum

Person.printNum()
slots

动态语言:可以在运行过程中,修改代码
静态语言:编译时已经确定好代码,运行过程中不能修改

__slots__作用:限制实例的属性

class Person(object):
    __slots__ = ("name", "age")
    
p = Person()
p.name = "alogy"
p.age = 24
    

Note:
__slots__定义的属性仅对当前类实例起作用,对继承的子类是不起作用

生成器

目标:列表中有大量数据,还不想占用大量内存空间。

生成器特点:保存了一套生成数值的算法。(什么时候需要使用到了,才去生成。)

生成器定义方法

方法1:()

a = (x for x in range(10))
print(a)

方法2: yield

def createNum():
    print("--start")
    a,b = 0,1
    for i in range(5):
        print("--11")
        yield b
        print("--22")
        a,b = b,a+b
        print("--33")
    print("--end")

t = createNum()

for num in t:
    print(num)

输出结果:

--start
--11
1
--22
--33
--11
1
--22
--33
--11
2
--22
--33
--11
3
--22
--33
--11
5
--22
--33
--end

send方法: 与yield的结果配合使用,使得yield执行的时候,外部可以传递参数到生成器中。
能够执行next()且还可以传递参数

def test():
    i = 0
    while i < 5:
        temp = yield i
        print(temp)
        i += 1

t = test()
print(t.next()) 
# 0
print(t.next()) 
# None
# 1
print(t.send("args"))
# args
# 2      

Note:
send()第一次直接调用报错,是参数不知道给那个函数。
报错为:

Traceback (most recent call last):
  File "", line 1, in 
TypeError: can"t send non-None value to a just-started generator

解决方法:

通过next()先调用一次,然后再使用send()

第一次调用send(None)传递空值进去,后续几次传递该传递的值

完成多任务
def test1():
    while True:
        print("test1")
        yield None

def test2():
    while True:
        print("test2")
        yield None

t1 = test1()
t2 = test2()

while True:
    t1.next()
    t2.next()

一齐执行test1(),test2(),test3(),三个while True同时执行
三个多任务或者三个以上同时执行称之为:协程

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/41392.html

相关文章

  • Python中的函数装饰器和闭包

    摘要:变量查找规则在中一个变量的查找顺序是局部环境,闭包,全局,内建闭包引用了自由变量的函数。闭包的作用闭包的最大特点是可以将父函数的变量与内部函数绑定,并返回绑定变量后的函数,此时即便生成闭包的环境父函数已经释放,闭包仍然存在。 导语:本文章记录了本人在学习Python基础之函数篇的重点知识及个人心得,打算入门Python的朋友们可以来一起学习并交流。 本文重点: 1、掌握装饰器的本质、功...

    caozhijian 评论0 收藏0
  • Python中的上下文管理器和else块

    摘要:上下文管理器协议包含和两个方法。因此必要时在上下文管理器函数中使用语句防范错误。构建临时忽略指定异常的上下文管理器。这是个基类,用于定义基于类的上下文管理器。块结束时,按照后进先出的顺序调用栈中各个上下文管理器的方法。 导语:本文章记录了本人在学习Python基础之控制流程篇的重点知识及个人心得,打算入门Python的朋友们可以来一起学习并交流。 本文重点: 1、掌握if语句之外的el...

    Michael_Lin 评论0 收藏0
  • Python装饰器、迭代器和成器

    摘要:在学习的时候,三大名器对没有其他语言编程经验的人来说,应该算是一个小难点,本次博客就博主自己对装饰器迭代器和生成器理解进行解释。 在学习python的时候,三大名器对没有其他语言编程经验的人来说,应该算是一个小难点,本次博客就博主自己对装饰器、迭代器和生成器理解进行解释。 装饰器 什么是装饰器?装饰从字面意思来谁就是对特定的建筑物内按照一定的思路和风格进行美化的一种行为,所谓器就是工具...

    30e8336b8229 评论0 收藏0
  • 流畅的python读书笔记-第七章-函数装饰器和闭包

    摘要:函数装饰器和闭包严格来说,装饰器只是语法糖。何时执行装饰器它们在被装饰的函数定义之后立即运行。装饰器突出了被装饰的函数的作用,还便于临时禁用某个促销策略只需把装饰器注释掉。 函数装饰器和闭包 严格来说,装饰器只是语法糖。如前所示,装饰器可以像常规的可调用对象那样调用,其参数是另一个函数。有时,这样做更方便,尤其是做元编程(在运行时改变程序的行为)时。 Python何时执行装饰器 它们在...

    Hydrogen 评论0 收藏0
  • python装饰器和描述器的使用总结

    摘要:所有的描述器协议如下如果一个对象同时定义了和它叫做资料描述器。仅定义了的描述器叫非资料描述器描述器在属性访问时被自动调用。 被某些中文教程坑过,我的建议是有问题看官方文档,即使没有很详细的例子,至少不坑 装饰器 毫无疑问在python中用得非常多 def deco(func): def _deco(): print before invoked ...

    xietao3 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<