zoukankan      html  css  js  c++  java
  • 自定义魔法方法(下)

    一、str

    在print输出的时候会自动调用__str__
    我们在自定义的时候必须要有返回值,且必须为字符串

    打印时触发

    class Foo:
        def __init__(self, name, age):
            """对象实例化的时候自动触发"""
            self.name = name
            self.age = age
    
        def __str__(self):
            print('打印的时候自动触发,但是其实不需要print即可打印')
            return f'{self.name}:{self.age}'  # 如果不返回字符串类型,则会报错
    obj = Foo('nick', 18)
    print(obj)  # obj.__str__() # 打印的时候就是在打印返回值
    ====>打印的时候自动触发,但是其实不需要print即可打印
    ====>nick:18
    obj2 = Foo('tank', 30)
    print(obj2)
    ====>打印的时候自动触发,但是其实不需要print即可打印
    ====>tank:30
    

    二、repr

    str函数或者print函数—>obj.str()
    repr或者交互式解释器—>obj.repr()
    如果str没有被定义,那么就会使用repr来代替输出
    注意:这俩方法的返回值必须是字符串,否则抛出异常

    class School:
        def __init__(self, name, addr, type):
            self.name = name
            self.addr = addr
            self.type = type
    
        def __repr__(self):
            return 'School(%s,%s)' % (self.name, self.addr)
    
        def __str__(self):
            return '(%s,%s)' % (self.name, self.addr)
    
    s1 = School('oldboy1', '北京', '私立')
    print('from repr: ', repr(s1))
    =====>from repr:  School(oldboy1,北京)
    print('from str: ', str(s1))
    ====>from str:  (oldboy1,北京)
    print(s1)
    ====>(oldboy1,北京)
    s1  # jupyter属于交互式
    ====>School(oldboy1,北京)
    

    三、实现迭代器(next__和__iter)

    简单示例
    死循环

    class Foo:
        def __init__(self, x):
            self.x = x
    
        def __iter__(self):
            return self
    
        def __next__(self):
            self.x += 1
            return self.x
    f = Foo(3)
    for i in f:
        print(i)
    

    加上StopIteration异常

    class Foo:
        def __init__(self, start, stop):
            self.num = start
            self.stop = stop
    
        def __iter__(self):
            return self
    
        def __next__(self):
            if self.num >= self.stop:
                raise StopIteration
            n = self.num
            self.num += 1
            return n
    f = Foo(1, 5)
    
    from collections import Iterable, Iterator
    print(isinstance(f, Iterator))
    ====>True
    
    for i in Foo(1, 5):
        print(i)
    ====>1
    ====>2
    ====>3
    ====>4
    

    模拟range

    class Range:
        def __init__(self, n, stop, step):
            self.n = n
            self.stop = stop
            self.step = step
    
        def __next__(self):
            if self.n >= self.stop:
                raise StopIteration
            x = self.n
            self.n += self.step
            return x
    
        def __iter__(self):
            return self
    for i in Range(1, 7, 3):
        print(i)
    ====>1
    ====>4
    

    斐波那契数列

    class Fib:
        def __init__(self):
            self._a = 0
            self._b = 1
    
        def __iter__(self):
            return self
    
        def __next__(self):
            self._a, self._b = self._b, self._a + self._b
            return self._a
    
    f1 = Fib()
    
    for i in f1:
        if i > 100:
            break
        print('%s ' % i, end='')
    ====>1 1 2 3 5 8 13 21 34 55 89
    
    

    四、module

    module 表示当前操作的对象在那个模块

    print(obj.__module__)  # 输出 lib.aa,即:输出模块
    

    五、class

    class表示当前操作的对象的类是什么

    print(obj.__class__)  # 输出 lib.aa.C,即:输出类
    

    六、实现文件上下文管理(enter__和__exit)

    我们知道在操作文件对象的时候可以这么写

    with open('a.txt') as f:
        '代码块'
    

    上述叫做上下文管理协议,即with语句,为了让一个对象兼容with语句,必须在这个对象的类中声明enter和exit方法

    上下文管理协议

    class Open:
        def __init__(self, name):
            self.name = name
    
        def __enter__(self):
            print('出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量')
            # return self
        def __exit__(self, exc_type, exc_val, exc_tb):
            print('with中代码块执行完毕时执行我啊')
    
    
    with Open('a.txt') as f:
        print('=====>执行代码块')
        # print(f,f.name)
    
    出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量
    =====>执行代码块
    with中代码块执行完毕时执行我啊
    

    exit()中的三个参数分别代表异常类型,异常值和追溯信息,with语句中代码块出现异常,则with后的代码都无法执行

    class Open:
        def __init__(self, name):
            self.name = name
    
        def __enter__(self):
            print('出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量')
    
        def __exit__(self, exc_type, exc_val, exc_tb):
            print('with中代码块执行完毕时执行我啊')
            print(exc_type)
            print(exc_val)
            print(exc_tb)
    
    try:
        with Open('a.txt') as f:
            print('=====>执行代码块')
            raise AttributeError('***着火啦,救火啊***')
    except Exception as e:
        print(e)
    
    出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量
    =====>执行代码块
    with中代码块执行完毕时执行我啊
    <class 'AttributeError'>
    ***着火啦,救火啊***
    <traceback object at 0x1065f1f88>
    ***着火啦,救火啊***
    

    如果__exit()返回值为True,那么异常会被清空,就好像啥都没发生一样,with后的语句正常执行

    class Open:
        def __init__(self, name):
            self.name = name
    
        def __enter__(self):
            print('出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量')
    
        def __exit__(self, exc_type, exc_val, exc_tb):
            print('with中代码块执行完毕时执行我啊')
            print(exc_type)
            print(exc_val)
            print(exc_tb)
            return True
    
    with Open('a.txt') as f:
        print('=====>执行代码块')
        raise AttributeError('***着火啦,救火啊***')
    print('0' * 100)  #------------------------------->会执行
    
    出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量
    =====>执行代码块
    with中代码块执行完毕时执行我啊
    <class 'AttributeError'>
    ***着火啦,救火啊***
    <traceback object at 0x1062ab048>
    0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
    

    模拟open

    class Open:
        def __init__(self, filepath, mode='r', encoding='utf-8'):
            self.filepath = filepath
            self.mode = mode
            self.encoding = encoding
    
        def __enter__(self):
            # print('enter')
            self.f = open(self.filepath, mode=self.mode, encoding=self.encoding)
            return self.f
    
        def __exit__(self, exc_type, exc_val, exc_tb):
            # print('exit')
            self.f.close()
            return True
    
        def __getattr__(self, item):
            return getattr(self.f, item)
    
    
    with Open('a.txt', 'w') as f:
        print(f)
        f.write('aaaaaa')
        f.wasdf  #抛出异常,交给__exit__处理
    
    <_io.TextIOWrapper name='a.txt' mode='w' encoding='utf-8'>
    

    优点:
    1、使用with语句的目的就是把代码块放入with中执行,with结束后,自动完成清理工作,无须手动干预
    2、在需要管理一些资源比如文件,网络连接和锁的编程环境中,可以在exit中定制自动释放资源的机制,你无须再去关系这个问题,这将大有用处

  • 相关阅读:
    MySQL主从复制的作用?
    MySQL的逻辑架构
    SQL语句的执行流程
    Count(*)在不同引擎的实现方式
    视图
    MySQL经典练习题(五)
    pyinstaller基本操作
    git基本操作
    Ubuntu安装tensorflow
    ScrollView can host only one direct child
  • 原文地址:https://www.cnblogs.com/qiukangle/p/14248364.html
Copyright © 2011-2022 走看看