zoukankan      html  css  js  c++  java
  • 面向对象进阶

    一.多态

    多态:一种事物具备多种不同的形态

    多态性:具有不同功能的函数可以使用相同的函数名,这样就可以用一个函数名调用不同内容的函数。

    多态的好处:降低使用难度

    class chicken:
        def bark(self):
            print('窝窝')
    
        def spawn(self):
            print('wowowo')
    
    
    class duck:
        def bark(self):
            print('gaga')
    
        def spawn(self):
            print('下鸭蛋')
    
    class goose:
        def bark(self):
            print('ga~ga')
    
        def spawn(self):
            print('下e蛋')
    
    def manage(obj) :
        obj.bark()
        obj.spawn()
    j = chicken()
    d = duck()
    g = goose()
    
    manage(j)
    manage(d)
    manage(g)
    View Code

    多态的实现方式:

    接口,抽象类,鸭子类型

    二.进阶方法

    1.__isinstance__与__issubclass __

    isinstance(obj,cls)检查是否obj是否是类 cls 的对象
    class foo:
        pass
    
    obj = foo()
    abc = 123
    print(isinstance(obj,foo))
    print(isinstance(abc,foo))
    View Code
    issubclass(sub, super)检查sub类是否是 super 类的派生类
    class Foo(object):
        pass
    
    
    class Bar(Foo):
        pass
    
    
    print(issubclass(Bar, Foo))
    View Code

    2.__str__与__repr__

    __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)
    # obj.__str__()
    print(obj)
    View Code

    __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))
    # print('from str: ', str(s1))
    print(s1)
    View Code
    str函数或者print函数--->obj.__str__()

    repr或者交互式解释器--->obj.__repr__()

    注意:这俩方法的返回值必须是字符串,否则抛出异常

    3.__del__与__call__

    __del__ 析构方法(函数),当对象在内存中被释放时,自动触发执行。
    class Foo:
    
        def __del__(self):
            print('执行我啦')
    
    f1=Foo()
    f2 = Foo()
    del f1
    print('------->')
    # 执行时机: 手动删除对象时立马执行,或是程序运行结束时也会自动执行
    # 使用场景: 可以手动回收系统相关资源
    View Code

    __call__ 对象后面加括号,触发执行。

    # call 对象后面加括号,触发执行。
    # 注:构造方法的执行是由创建对象触发的,即:对象 = 类名() ;
    # 而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()
    class Foo:
    
        def __init__(self):
            pass
    
        def __call__(self, *args, **kwargs):
            print('__call__')
    
    
    obj = Foo()  # 执行 __init__
    obj()  # 执行 __call__
    Foo()()
    View Code

    4.__slots__

     __slots__ 的功能:节省内存(固定对象的内存大小) 防止用户给实例增加新的属性
    import sys
    class Person:
    
        __slots__ = ["name"]
        def __init__(self,name):
            self.name = name
    
    p =  Person("jck")
    
    # 查看内存占用
    print(sys.getsizeof(p))
    p.name = 20 # 无法添加
    
    # 使用__slots__以后__dict没有了__
    print(p.__dict__)
    View Code

    5.__getattr__  __setattr__ 和 __delattr__

    getattr 用点访问属性的时如果属性不存在时执行
    setattr 用点设置属性时
    delattr 用del 对象.属性 删除属性时 执行
    getattribute 该函数也是用来获取属性
    获取属性则先执行getattribute函数,如果没有拿到属性则继续调用 getattr函数,如果拿到了则直接返回
    class A:
    
        def __setattr__(self, key, value):
            print(key,value)
            super().__setattr__(key,value)
            # self.__dict__
    
    
        #
        def __delattr__(self, item):
            print("__delattr__")
            print(item)
            super().__delattr__(item)
    
        def __getattr__(self, item):
            print("__getattr__")
            return 1
    
        def __getattribute__(self, item):
            print("__getattribute__")
    
            return super().__getattribute__(item)
    
    #
    a = A()
    a.name = "xxx"
    print(a.name)
    
    del a.name
    print(a.name)
    View Code

    6.__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):
            del self.__dict__[key]
            print("__delitem__")
    
    
    a = A()
    # a.name = "jack"
    a["name"] = "jack"
    print(a["name"])
    del a["name"]
    print(a["name"])
    View Code

    三.运算符重载

    在我们使用抽象字符时,python解释器会按照符号规定的含义,调用对应的处理函数,。

    在我们需要自定义对象的比较规则时,就可在子类中覆盖 大于(gt) 等于(eq) 小于(lt)等一系列方法....

    class Student(object):
        def __init__(self, name, height, age):
            self.name = name
            self.height = height
            self.age = age
    
        def __gt__(self, other):
            # print(self)
            # print(other)
            # print("__gt__")
            return self.height > other.height
    
        # def __lt__(self, other):
        #     return self.height < other.height
    
        def __eq__(self, other):
            if self.name == other.name and self.age == other.age and self.height == other.height:
                return True
            return False
    
    
    stu1 = Student("jack", 180, 28)
    stu2 = Student("jack", 167, 28)
    print(stu1 < stu2)
    print(stu1> stu2)
    #大于和小于只要实现一个即可,符号如果不同  解释器会自动交换两个对象的位置 
    # print(stu1 == stu2)
    View Code

    四.迭代器协议

    迭代器:指具有__iter__和__next__的对象

    class MyRange:
    
        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 MyRange(1,10,2):
        print(i)
    View Code

    五.上下文管理

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

    class MyOpen(object):
    
        def __init__(self,path):
            self.path = path
    
        def __enter__(self):
            self.file = open(self.path)
            print("enter.....")
            return self.file
    
        def __exit__(self, exc_type, exc_val, exc_tb):
           # __exit__()中的三个参数分别代表异常类型,异常值和追溯信息
    
            print("exit...")
            print(exc_type,exc_val,exc_tb)
            self.file.close()
            # return True
            return False
    #exit函数 可以有一个bool类型返回值,True表示异常被抛出
    # False,异常未被处理。若上下文中出现异常,程序会被中断报错
    with MyOpen("a.txt") as m:
    #出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量
        print(m)
        print(m.read())
        # "123"+1
    #当代码执行完毕后执行exit, 或者遇到异常会立即执行exit, 并传入错误信息
    View Code

    优点:

    1. 把代码块放入with中执行,with结束后,自动完成清理工作,无须手动干预

    2. 在需要管理一些资源比如文件,网络连接和锁的编程环境中,可以在__exit__中定制自动释放资源的机制

     

     

  • 相关阅读:
    ios10 获取idfa的坑
    iOS 获取手机sim卡的运营商(移动,电信,联通) 相关信息
    iOS获取手机IP地址
    UIScrollView 与 touchesBegan 冲突解决方法
    32位与64位基础
    MySQL数据库基础_表&简单查询
    MySQL数据库基础
    Java_File、递归
    Java_lambda表达式
    Java线程锁,等待唤醒和线程池
  • 原文地址:https://www.cnblogs.com/Cpsyche/p/11266946.html
Copyright © 2011-2022 走看看