zoukankan      html  css  js  c++  java
  • 多态及类的魔法函数

    多态

    概念:

    一种事物的多种形态

    官方解释:不同类型的对象调用同一个方法得到不同结果(多个对象有相同方法)

    多态是种思想,不是方法

    实例

    '''A,B,C都具有相同的功能,可以定义一个函数进行调用,这就是多态'''
    
    
    class A:
        def run(self):
            print('A在慢跑...')
    
        def eat(self):
            print('A在吃饭...')
    
    
    class B:
        def run(self):
            print('B在快跑...')
    
        def eat(self):
            print('B在吃面...')
    
    
    class C:
        def run(self):
            print('C对断了不能跑...')
    
        def eat(self):
            print('Cly在吃be...')
    
    
    def manage(obj):
        obj.run()
        obj.eat()
    
    a = A()
    b = B()
    c = C()
    
    manage(a)
    manage(b)
    manage(c)

    对于使用者来说降低了使用难度

    接口 抽象类 鸭子类型都是具备写出多态代码的,最简单的就是鸭子类型

    isinstance

    判断一个对象是否是某个类的实例

    参数1 要判断的对象

    参数2 要判断的类型

     

    issubclass

    判断一个类是否是另一个类的子类

    参数一是子类

    参数二是父类

    class A:
        pass
    
    class B(A):
        pass
    
    a = A()
    print(isinstance(a, A))
    True
    print(issubclass(B, A))
    True

    str

    __str__在默认情况下,打印对象会得到对象的内存地址,内存地址就是__str__函数的返回值,
    我们可以将__str__进行覆盖,自定义该函数的返回值

    class A:
    
        def __str__(self):
            return 'hello'
    
    
    a = A()
    print(a)  # hello
    返回值必须是字符串形式

    del

    执行时机:在对象被手动删除或程序运行结束时执行
    使用场景:当你的对象在使用过程中,打开了不属于解释器的资源:例如文件,网络端口

    class A:
    
        def __init__(self, path):
            self.file = open(path, 'rt', encoding='utf8')
    
        def read(self):
            return self.file.read()
    
        # 在这里可以确定一个事,这个对象肯定不使用了 所以可以放心的关闭文件了
        def __del__(self):
            print('del run')
            self.file.close() 
    
    
    a = A('test.txt')
    print(a.read())

    call

    在调用对象时,会自动执行  (既对象加括号)
    class A:
        def __init__(self):
            pass
    
        def __call__(self, *args, **kwargs):
            print('call run')
            print(args)
            print(kwargs)
    
    a = A()
    a('a', 'b', x=10, y=20)
    '''
    call run
    ('a', 'b')
    {'x': 10, 'y': 20}
    '''

    slots

    该属性是一个类属性,用于优化对象内存占用
    优化的原理,将原本不固定的属性数量,变得固定了
    这样的解释器就不会为这个对象创建名称空间,所以__dict__也没了  
    从而达到减少内存开销的效果 
    
    另外当类中出现了slots时将导致这个类的对象无法在添加新的属性
    # slots的使用
    class Person:
    
        __slots__ = ['name','age']
        def __init__(self,name,age):
            self.name = name
            self.age = age
    
    
    p = Person('cly', 17)
    p.height = 170 # 无法进行添加
    p.__dict__  # dict也没有了 

    getattr setattr delattr

    getattr 用点访问属性的时如果属性不存在时执行
    setattr 用点设置属性时
    delattr 用del 对象.属性  删除属性时 执行
    
    这几个函数反映了 python解释器是如何实现 用点来访问属性 
    
    getattribute 该函数也是用来获取属性
    在获取属性时如果存在getattribute则先执行该函数,如果没有拿到属性则继续调用 getattr函数,如果拿到了则直接返回
    class A:
    
        def __getattr__(self, item):
            print('哈哈哈')
    
        def __setattr__(self, key, value):
            print('setattr run')
            self.__dict__[key] = value
    
        def __delattr__(self, item):
            print('__delattr__')
            self.__dict__.pop(item)
    
    
    a = A()
    a.name = 'cly'
    # print(a.name)
    '''
    setattr run
    cly
    '''
    print(a.name)
    del a.name  # 删除属性时,会执行__delattr__函数
    print(a.name)  # 用点访问属性的时如果属性不存在时执行__getattr__

    []的原理

    getitem setitem delitem

    任何的符号 都会被解释器解释成特殊含义 ,例如 . [] ()

    getitem 当你用中括号去获取属性时 执行
    setitem  当你用中括号去设置属性时 执行
    delitem 当你用中括号去删除属性时 执行
    class A:
    
        def __getitem__(self, item):
            print('__getitem__')
            return self.__dict__[item]
    
        def __setitem__(self, key, value):
            print('__setitem__')
            self.__dict__[key] = value
    
        def __delitem__(self, key):
            print('__delitem__')
            self.__dict__.pop(key)
    
    
    a = A()
    a['name'] = 'cly'
    print(a['name'])
    '''
    __setitem__
    __getitem__
    cly
    '''
    del a['name']
    print(a['name'])

    运算符重载

    当我们在使用某个符号时,python解释器都会为这个符号定义一个含义,同时调用对应的处理函数, 当我们需要自定义对象的比较规则时,就可在子类中覆盖 大于 等于 等一系列方法....

    案例:

    原本自定义对象无法直接使用大于小于来进行比较 ,我们可自定义运算符来实现,让自定义对象也支持比较运算符

    class A:
    
        def __init__(self,name,age,height):
            self.name = name
            self.age = age
            self.height = height
    
        def __gt__(self, other):
            return self.age > other.age
    
        def __lt__(self, other):
            return self.height < other.height
        
        def __eq__(self, other):
            return self.name == other.name
    
    a = A('rose', 18, 180)
    b = A('jack', 19, 190)
    print(a > b)
    print(a < b)
    print(a == b)

    上述代码中,other指的是另一个参与比较的对象,

    迭代器协议

    迭代器是指具有__iter__和__next__的对象
    我们可以为对象增加这两个方法来让对象变成一个迭代器 
    class A:
    
        def __init__(self, start, end, step):
            self.start = start
            self.end = end
            self.step = step
    
        def __iter__(self):
            return self
    
        def __next__(self):
            a = self.start
            self.start += self.step
            if a < self.end:
                return a
            else:
                raise StopIteration
    
    for i in A(1,10,2):
        print(i)

    上下文管理

    上下文 context

    这个概念属于语言学科,指的是一段话的意义,要参考当前的场景,既上下文

    在python中,上下文可以理解为是一个代码区间,一个范围 ,例如with open 打开的文件仅在这个上下文中有效

     

    涉及到的两个方法:

    enter

    表示进入上下文,(进入某个场景 了)

    exit

    表示退出上下文,(退出某个场景 了)

     

    当执行with 语句时,会先执行enter ,

    当代码执行完毕后执行exit,或者代码遇到了异常会立即执行exit,并传入错误信息

    包含错误的类型.错误的信息.错误的追踪信息

    注意:

    enter 函数应该返回对象自己 
    exit函数 可以有返回值,是一个bool类型,用于表示异常是否被处理,仅在上下文中出现异常有用
    如果为True 则意味着,异常以及被处理了 
    False,异常未被处理,程序将中断报错
    class A:
    
        def __init__(self, path):
            self.path = path
    
        def __enter__(self):
            self.file = open(self.path,'r',encoding='utf8')
            print('__enter__')
            return self
    
        def __exit__(self, exc_type, exc_val, exc_tb):
            print('__exit__')
            print(exc_type, exc_val, exc_tb)
            self.file.close()
            return True  # 返回True时,并不会报错,会将错误信息传入
    
    with A('test.txt') as f:
        '123'+1
        print(f.file.read())
  • 相关阅读:
    第三方模块加载时出现XXX运行 提示错误:无法加载文件 C:UsersgxfAppDataRoaming pmXXX.ps1,因为在此系统上禁止运行脚本。
    node模块化
    前端面试集锦
    将字符转换成驼峰表示法
    JavaScript数据处理
    大数据基础整合
    移动端网页特效
    本地存储
    DOM重点核心
    触发器SQL
  • 原文地址:https://www.cnblogs.com/asdaa/p/11265056.html
Copyright © 2011-2022 走看看