zoukankan      html  css  js  c++  java
  • 面向对象之多态以及魔法函数

    一:多态

    【1】基础概念

    (1)基础概念:

      (1)一种事物拥有多种形态:

        例如:水--->气态--->液态--->固态

      (2)在python中是多个对象可以相应同一种方法 产生不同的结果

    PS:多态不是一种语法 而是一种特殊的状态 特性 即多个对象有相同的使用方法

    例如:

    # 案例一
    class Chicken:
        def span(self):
            print('下鸡蛋')
    
    class Duck:
        def span(self):
            print('下鸭蛋')
    
    class Goose:
        def span(self):
            print('下鹅蛋')
    
    j = Chicken()
    
    y = Duck()
    
    e = Goose()
    
    j.span() # 下鸡蛋
    y.span() # 下鸭蛋
    e.span() # 下鹅蛋
    
    # 案例二
    a = '10'
    
    b = [10]
    
    c = (10,)
    
    print(len(a),len(b),len(c)) # 2 1 1
    多态案例

    (2)优点:

      (1)增加的程序的灵活性 以不变应万变 无论对象怎么变化 使用者调用方式不变

      (2)如果通过继承类 而创建一个新的类 使用者无需更改自己的代码 还是以原始方式调用

    PS:继承 抽象类 鸭子类型都可以写出具备多态的代码 但是鸭子类型更加方便以及快捷

    【2】内置方法

    (1)isinstance:

    作用:判断一个对象是否为一个类的实例

    例如:

    def add_num(x,y):
        # 判断整形是否为某个类
        if isinstance(x,int) and isinstance(y,int):
            return x + y
        return '错误的相加'
    
    # 情景一
     print(add_num('10',20)) # 报错 字符串与整形不能相加
    
    # 情景二 print(add_num('10',20)) # 错误的相加
    
    # 情景三 判断所属的类
    print(add_num(10,20)) # 30

    PS:

    (1)参数一:所传的对象

    (2)参数二:所属的类

    (2)issubclass:

    作用:判断一个类是否为一个类的子类

    例如:

    class Animal:
        def eat(self):
            print('动物需要吃东西!')
    
    class Pig(Animal):
        def eat(self):
            print('猪正在吃猪食!')
    
    class Tree:
        def sunshine(self):
            print('树在进行光合作用!')
    
    def manage(animal):
        # 判断一个类是否为另外一个类的子类
        if issubclass(type(animal),Animal):
            animal.eat()
        else:
            print('不是动物 而是植物!')
    
    
    
    pig = Pig()
    tree = Tree()
    
    manage(pig)
    # 没加条件判断之前
    manage(tree)  # 报错 因为tree没有继承Animal
    
    # 添加添加判断
    manage(tree) # 不是动物 而是植物!
    判断一个类是否为另外一个类子类

    (3)str

    (1)作用:在对象被转换成字符串的时候被调用 调用的结果就是函数的返回值

    例如:

    class Person:
        def __str__(self):
            print('run')
    
            return 'SR'
    
    p = Person()
    
    # 没加返回值之前
    print(p)  # 报错 希望得到一串字符串返回值
    
    # 添加返回值
    print(p)  # 执行函数代码 并且有返回值
    
    str(p) # run
    #PS:对象在被转换成字符串的时候 调用__str__函数

    PS:

    (1)如果对象在被转换成字符串的时候 首先会执行__str__的执行

    (2)__str__执行完毕之后 在进行函数的打印

    (4)del:

    作用:手动删除对象的时候 或者程序结束会立马执行释放内存

    使用场景:但是其作用不是用来清除解释器中的资源 而是不属于解释器的资源 例如某些文本 端口号等

    例如:

    class  File:
        # 创建文件的初始属性 赋值函数的地址
        def __init__(self,path):
            self.file = open(path,'rt',encoding='utf-8')
    
        def read(self):
            # 返回读取的文件
            return self.file.read()
    
        def __del__(self):
            self.file.close()
    
    
    file = File('a.txt')
    print(file.read())
    file .__del__()
    print(file.read()) # 报错显示文件已经被关闭

    PS:上述可以通过del删除非解释器的资源

    (5)call

    作用:在调用对象的时候被执行

    例如:

    class A:
        def __call__(self, *args, **kwargs):
            print("call run")
            print(args)
            print(kwargs)
    
    
    a = A()
    a(18,a = 100)

    (6)solts

    作用:

      (1)一种优化机制 防止浪费不必要的内存

      (2)其将不固定的属性数量变的固定了

      (3)这样解释器不会为对象创建名称空间 减少了__dict__

      (4)当类中出现了该参数 对象也不能在添加属性

    例如:

    import sys
    class Person:
        __slots__ = ['name']
    
        def __init__(self,name):
            self.name = name
    
    p = Person('SR')
    # print(p.__dict__) # 报错
    
    # 加slots之前
    print(sys.getsizeof(p)) # 56
    
    # 加slots
    print(sys.getsizeof(p)) # 48
    
    # 添加新属性
    p.age = 20 # 报错

    (7)

    (1)getattr

      作用:当用点访问属性的时候 如果属性不存在则会执行

    (2)setattr

      作用:当用点设置属性的时候 会执行改函数

    (3)delattr

      作用:用del 删除属性的时候 会执行改函数

    (4)getattribute

      作用:当在调用属性的时候 如果属性存在则会调用该函数并且将属性值返回 如果属性不存在的情况下则会调用getattr

    例如:

    class A:
    
        def __setattr__(self, key, value):
    
            print("__setattr__")
            self.__dict__[key] = value
    
        def __delattr__(self, item):
            print("__delattr__")
            self.__dict__.pop(item)
    
    
        def __getattr__(self, item):
            print("__getattr__")
            return 1
    
        def __getattribute__(self, item):
            print("__getattribute__")
            # return self.__dict__[item]
            return super().__getattribute__(item)
    方法演示

    PS:

    (1)当在__getattribute__代码块中,再次执行属性的获取操作时,会再次触发__getattribute__方法的调用,代码将会陷入无限递归,直到Python递归深度限制(重载__setter__方法也会有这个问题)

    (2)为了避免无限递归,应该把获取属性的方法指向一个更高的超

    (8)

    (1)getitem

      作用:当使用[]调用属性的时候会执行该函数

    (2)setitem

      作用:当使用[]设置属性的时候 会执行该函数

    (8)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"])

    (9)运算符重载:

    作用:

    (1)当在python中调用某个符号的时候 python都会为该符号定义一个含义 并且调用该含义背后所对应的函数

    (2)当我们需要自己定义比较规则的时候 就可以自己在子类中覆盖父类中所对应的 大于 等于 小于等方法

    例如:

    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",180,28)
    # print(stu1 < stu2)
    print(stu1 == stu2)

    PS:

    (1)gt 大于 lt 小于 eq等于

    (2)在代码中other指的是其余对象 self作为本身

    (9)上下文管理:

    (1)在生活中一段话的意义要看情景 上问和下文有关联

    (2)在python中上下文可以看做一个范围 某些代码只在一个范围内有效

      (1)enter 进入上下文

      (2)exit 退出上下文

    例如:

    class MyOpen(object):
    
    
        def __init__(self,path):
            self.path = path
    
        def __enter__(self):
            self.file = open(self.path)
            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

    (1)代码执行完毕之后 执行exit结束上下文

    (2)代码执行错误也会执行exit结束上下文

    (3)其会返回错误类型 错误的信息 以及错误的路径追踪信息

    PS:

    (1)enter返回值为对象自己

    (2)exit返回值为布尔值 表示错误信息是否被处理 如果为真则表示已经处理 为假则未处理

  • 相关阅读:
    Oracle面试题目及解答
    java -jar Incompatible argument to function
    plsql 查询到别的用户下面的表
    redis数据类型[string 、list 、 set 、sorted set 、hash]
    redis-cli 常用命令
    js判断浏览器,包括Edge浏览器
    HTMl5的sessionStorage和localStorage
    JS实现密码加密
    sprintf.js
    js-crc32
  • 原文地址:https://www.cnblogs.com/SR-Program/p/11267157.html
Copyright © 2011-2022 走看看