面向对象之多态以及魔法函数
一:多态
【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返回值为布尔值 表示错误信息是否被处理 如果为真则表示已经处理 为假则未处理