• 面向对象进阶(二)


    一、item系列:getitem、_setitem__和__delitem_
    二、类的特殊变量:_slots_
    三、迭代器协议:_iter__和__next_
    四、_module__和__class_
    五、类的描述信息:_doc_
    六、析构方法:_del_
    七、_enter__和__exit_
    八、call
    九、元类

    item系列:

    • 把对象操作属性模拟成字典的格式
    class Foo:
        def __init__(self, name):
            self.name =name
        def __getitem__(self, item):
            return self.__dict__[item]
        def __setitem__(self, key, value):
            self.__dict__[key] = value
        def __delitem__(self, key):
            self.__dict__.pop(key)      
    f = Foo('egon')
    
    print(f['name'])
    
    f['age'] = 18
    print(f.__dict__)
    
    del f['age']
    print(f.__dict__)
    

    二、slots

    • 属于类的变量,类型可以是列表、元组、可迭代对象字符串
    • 在类中声明好__slots__变量后,可以直接通过对象调用
    • 同时,对象也无法添加新的变量
    class Foo():
        __slots__ = ['a','b','c']
    
    f = Foo()
    f.a = 1
    f.b = 2
    f.c = 3
    
    print(f.a,f.b,f.c)
    print(f.__dict__)
    

    三、迭代器协议:iter__和__next

    迭代器的定义:

    • 只要对象本身有__iter__方法,那对象就是可迭代的;
    • 调用iter()或者__iter__方法可以将列表、元组等变成迭代器;
    • 调用next()或者__next__方法可以将返回迭代器中的每一个元素;如果对象具有__iter__方法,说明该对象是可迭代对象

    以下定义类时,通过在类中增加__iter__和__next__方法,实例化的对象就是可迭代的:

    class Foo:
        def __init__(self, start):
            self.start = start
        def __iter__(self):
            return self
        def __next__(self):
            if self.start >10:
                raise StopIteration
            n = self.start
            self.start += 1
            return n
    
    f = Foo(0)
    print(next(f))
    print(next(f))
    
    for i in f:
        print(i)
    

    举例:使用__iter__和__next__实现range()方法:

    class my_range:
        def __init__(self, start, end):
            self.start = start
            self.end = end
    
        def __iter__(self):
            return self
    
        def __next__(self):
            if self.start > self.end:
                raise StopIteration
            n = self.start
            self.start += 1
            return n
    
    for i in my_range(0,3):
        print(i)
    

    四、module__和__class

    module 表示当前操作的对象属于哪个模块

    class 表示当前操作的对象属于哪个类

    五、doc

    doc 类的描述信息,而且无法被继承

    六、析构方法:del

    • 当对象在内存中被释放时,自动触发本方法
    • 属于解释器在函数内部垃圾回收时自动执行的方法

    举例:根据之前使用授权方式(自定义数据类型方式之一),自定义的open()方法,可以应用析构方法__del__进行优化,当调用的方法结束后自动关闭文件

    class Open:
        def __init__(self, file_path, mode = 'r', encoding = 'utf8'):
            self.f = open(file_path, mode = mode, encoding = encoding)
    
        def write(self, value):
            self.f.write(value)
    
        def __del__(self):
            self.f.close()
            print('---del')
    
    f = Open('a.txt','w')
    f.write('abgc')
    def f    #此处不调用def f也可以,因为会自动调用__del__
    

    七、enter__和__exit

    • 上下文管理协议:就是在文件操作经常用到with open() as f中的with语句
    • 如果对象要兼容with语句,需要在对象的类中声明__enter__和__exit__方法
    • 其中,在实例化对象前出现with时,对象的__enter__方法被调用,并将返回值赋值给as后的变量(文件句柄)
    • 其中,with中的代码执行完毕或者代码抛异常时执行__exit__方法
    • __exit__中的三个参数分别代表异常类型、异常值和追述信息,当with代码块缩进的代码出现问题,抛出异常,则with代码块中后面的代码无法被执行
    • __exit__中的参数可以设置抛出异常内容,并返回True,相当于自行处理异常内容,不影响with代码中后面的代码执行

    举例:自定义的open()方法,也可以使用__enter__和__exit__方法来实现上下文管理协议,获取文件句柄通过__enter__,当with代码执行完毕后调用__exit__关闭文件

    class Open:
        def __init__(self, file_path, mode = 'r', encoding = 'utf8'):
            self.f = open(file_path, mode=mode, encoding=encoding)
            
        def __enter__(self):
            return self.f
    
        def __exit__(self, exc_type, exc_val, exc_tb):
            self.f.close()
    
    with Open('a.txt','r') as a:
        for i in a:
            print(i)
    

    八、call

    对象加括号,触发执行。

    class Foo:
        def __init__(self):
            pass
    
        def __call__(self, *args, **kwargs):
            print('This is call')
    
    f = Foo()
    f() #对象加括号执行,结果:This is call
    

    九、元类

    • 类是元类的对象,可以利用元类来控制类的行为
    #type称为元类,是所有类的类,利用type模拟class关键字的创建过程
    def run(self):
        pass
    
    class_name = 'Spam'
    class_base = (object,)
    class_dict = {
        'x': 1,
        'run':run
    }
    
    bar = type(class_name,class_base,class_dict)
    print(bar)
    print(type(bar))
    print(bar.__dict__)
    
    #class封装了以上类的创建过程
    class spam:
        pass
    
    print(spam)
    print(type(spam))
    print(spam.__dict__)
    
    #利用type创建一个空类cls赋值给对象aaa
    aaa = type('cls',(),{})
    print(aaa)
    print(type(aaa))
    print(aaa.__dict__)
    

    举例:创建元类Mymeta,Foo继承Mymeta,元类中对继承Mymeta的类是否写注释__doc__做了限制:

    3FC53F9435B60B5B700F7F61CA77B8

  • 相关阅读:
    javascript 判断电话号码的格式
    JavaScript 'Pig latin is cool'==>'igPay atinlay siay oolcay'
    JavaScript 找出特殊数字如135 = 1^1 + 3^2 + 5^3
    nginx+Apache实现动静分离
    MYSQL数据库的主从复制
    Connection could not be established with host smtp.163.com [Connection timed out #110]
    Yii2 的 redis 应用
    Yii2 模块名、控制器名、方法名
    讯搜
    支付宝异步通知时间点分布
  • 原文地址:https://www.cnblogs.com/sunqim16/p/6763364.html
Copyright © 2020-2023  润新知