zoukankan      html  css  js  c++  java
  • chapter9.3、可调用对象,上下文管理

    可调用对象

    函数也是对象,函数可以调用,对象加上括号,就是对象调用自己的__call__方法,函数也是可调用对象

    def foo():
        print(foo.__module__,foo.__name__)
    foo()
    #等价于
    foo.__call__()

    都返回__main__ foo

    __call__      类中定义的方法,使实例可以像函数一样调用

    格式化返回坐标的点

    class Point:
        def __init__(self,x,y):
            self.x = x
            self.y = y
    
        def __call__(self, *args, **kwargs):
            return "<Point {}:{}>".format(self.x,self.y)
    
    p = Point(4,2)
    print(p)##返回实例的对象
    print(p())##返回<Point 4:2>,调用实例,调用了__call__

    加法器

    class Adder:
        def __call__(self,*args):
            ret = 0
            for x in args:
                ret += x
            self.ret = ret
            return ret
    
    adder=Adder()
    print(adder(1,2,3))
    print(adder.ret)

    斐波那契数列的实现

    class Fib:
        def __init__(self):
            self.items = [0,1,1]
    
        def __call__(self,n):
            if n < 0:
                raise IndexError('Wrong Index')
            if n < len(self.items):
                return self.items[n]
    
            for i in range(n-len(self.items)+1):
                self.items.append(self.items[-1]+self.items[-2])
            return self.items[n]
    
    fib = Fib()
    print(fib(5))

    使用类来实现斐波那契数列较为合适,还可以缓存,检索

    上下文管理

    文件IO操作可以对文件对象使用上下文管理,使用with...as语法

    对类使用上下文管理:

      3.5之前open一个class,返回AttributeError:__exit__

      3.6之后返回AttributeError:__enter__

    当一个对象同时实现了__enter__和__exit__,就属于上下文管理对象

    定义__enter__,进入对象相关的上下文,如果存在,with后又有as,就会将返回值绑定到as后的变量上

    __exit__,退出于此对象相关的上下文,exit里加关闭文件之类的操作

    进出with,打开调enter,结束调exit,

    import time
    class Point:
        def __init__(self):
            print('init')
            
        def __enter__(self):
            print("enter")
            return 100
        
        def __exit__(self, exc_type, exc_val, exc_tb):
            print('exit')
    
    with Point() as f:
        print('-'*30)
        print(f)
        time.sleep(5)
        print("_"*30)
    
    print('____________end____________')

    返回中可以看到执行顺序,with后边的实例先创建,调用__init__方法,后with打开调用__enter__,

    执行with中的语句,退出with时再调用__exit__,而且退出时无论上方如何执行都一定会被with清除占用的资源。

    with可以开启一个上下文运行环境,在执行前做一些准备工作,执行后做一些收尾工作

    with Point() as f:
        raise Exception('error')
        print('123')

    通过上个实验,可以看到,即使是异常的抛出都无法阻止with执行__exit__

    import sys
    with Point() as f:
        sys.exit(100)
        print('123')
    print('outer')

    这个例子更极端,直接退出当前解释器,也不会阻止with执行清理

    所以,上下文管理是安全的

    with语句

    class Point:
        def __init__(self):
            print('init')
    
        def __enter__(self):
            print('enter')def __exit__(self, exc_type, exc_val, exc_tb):
            print('exit')
    
    p = Point()
    with p as f:
        print(p==f)###返回False,as要求__enter__返回值赋给f
        print('~~~~~')

    以上代码缺少__enter__的返回值,所以不等

    class Point:
        def __init__(self):
            print('init')
    
        def __enter__(self):
            print('enter')
            return self
    
        def __exit__(self, exc_type, exc_val, exc_tb):
            print('exit')
    
    p = Point()
    with p as f:
        print(p==f)
        print('~~~~~')

    __enter__方法返回值就是上下文中使用的对象,with语法会把它的返回值赋给as字句的变量

    __exit__方法有三个参数,(self,exc_type,exc_value,traceback)

     这三个参数都与异常有关,如果没有异常这三个参数就是None。

    如果有异常,参数就有意义

    exc_type表示异常类型,exc_value,表示异常的值,traceback异常追踪的信息

    __exit__方法返回一个等效的True的值,则压制异常,否则抛出异常

    class Point:
        def __init__(self):
            print('init')
    
        def __enter__(self):
            print('enter')
            return self
    
        def __exit__(self, exc_type, exc_val, exc_tb):
            print(exc_type)##类型,此处返回Exception
            print(exc_val)##此处返回with中返回的异常值,"what's wrong"
            print(exc_tb)##返回异常追踪<traceback object at 地址>
            print('exit')
            return True###为等效True都会压制异常
        
    p = Point()
    with p as f:
        raise Exception("what's wrong")
        print('do sth')
        
    print('outer')

    enter不可加参数

    exit中traceback

    exit 的return为等效bool值True时,可以压制异常,为False时不压制

    资源申请和资源释放

    安全性

    装饰器,类成为装饰器

    inspcct看类的签名

    多个装饰器的顺序会有影响,???留问题了

    wrapper复习

    应用场景,增强功能类似装饰器,

    资源管理,链接管理’

    权限验证

    contextmanager

  • 相关阅读:
    Java Thread 总结
    用 for/in 在 Java 5.0 中增强循环
    JAVA中synchronized和lock详解
    centos vim的安装目录在哪里
    Cannot add task 'wrapper' as a task with that name already exists.
    servlet的生命周期
    I/O同个文件需要注意的问题
    分治策略---求最大子数组
    Java实现 100!的阶乘
    Java中方法的重载与覆盖(随笔01)
  • 原文地址:https://www.cnblogs.com/rprp789/p/9683844.html
Copyright © 2011-2022 走看看