面向对象
面向过程
| 也就是过程,解决过程的流程,相当于流水线一样的 |
| 把问题流程化 |
| 优点: |
| 将复杂的流程简单化 |
| 缺点: |
| 可扩展性差 |
面向对象
| 对象:特征与技能的结合体 |
| |
| 有点: |
| 可扩展性强 |
| 缺点: |
| 编程复杂高 |
| |
| 应用场景: |
| 用户需求经常变化,游戏,企业内的应用 |
| |
| |
| 类就是一系列对象相似特征与技能的结合体 |
| 强调:站在不同的角度中,得到的分离是不同的 |
| |
| 在现实世界:现有对象后总结出来类 |
| 在编程世界:先定义类,后调用类来产生对象 |
| |
| |
一切接对象
| 站在不同的角度上 定义的类是不同的 |
| 现实中的类不等于程序中的类 现实中的公司类,在程序中要拆分到部门,业务 |
| 有是为了编程需求 程序中定义的类在现实中是不存在的,比如策略类 显示中是不存在的,但是在程序中非常常见 |
| |
| python 一切皆对象 在python3中的统一类类型的概念 |
| |
| 比如: |
| class list 类 只是继承了 列表相似的功能进去 |
| |
| |
| l1 = [1,2,3] |
| l2 = [1,2,4] |
| 那么 l 变量就是list class类的实例化对象 name l 就可以使用list中的那个方法 |
| |
| 比如: l.append() |
基本使用
| |
| class 类名: |
| |
| def 方法名(self,参数1,参数2.....): |
| pass |
| |
| 执行类: |
| |
| 对象 实例化类 |
| 实例对象=类名() |
| |
| 实例对象.方法名(参数1,参数2...) |
| |
| |
| |
| |
| 案例: |
| class Name(object): |
| |
| def get_name(self): |
| return 'name' |
| |
| |
| |
| name = Name() |
| |
| name.get_name() |
1.初始化方法init
| 在实例化对象时,会自动触发__init__方法 |
| class 中的 name = Name() 被称为实例化对象 |
| |
| 1.init方法的定义 |
| class 类名: |
| def __init(self): |
| pass |
| |
| 2.对实例变量进行定义(当前类下的全部方法都可以使用) |
| class C: |
| def __init(self,val): |
| |
| self.val = val |
| self.a = '777' |
| C('123') |
| |
| 3.__init__的过程 |
| 1.执行class()实例化 |
| 2.在执行对class进行实例化时 会限制性__new__(cls)方法 创建一个内存区域 cls参数就是当前类本身 |
| 3.才会执行__init__(self,)方法self 是内部提供的参数,内部存储的是基于实例化的一个内存区域(默认为空),使用__init__方法可以将数据存储在方法中,通过self进行调用存储的数据 |
| 4.self 是个参数接收了class的实例化在new方法执行完毕创建内存区域后,init方法接收并且将方法参数存储到内存区域,使用self进行调用 |
| |
| |
| 4.当实例化两个对象时 内存地址时不同的 |
| class Name(object): |
| def __init__(self): |
| print('我是init方法') |
| |
| def __new__(cls, *more): |
| print('我是new方法') |
| return super().__new__(cls, *more) |
| |
| |
| name = Name() |
| print(id(name)) |
| name2 = Name() |
| print(id(name2)) |
| |
| 实例化时 将对象当成参数传入到self中,self内是一个内存区域,存放着类中的方法和数据。 |
2.class的成员修饰符
| 1.成员 类变量 实例变量 |
| 实例变量:封装到实例化对象中,只有实例化对象才能调用,在类中属于局部变量 |
| 类变量: 封装到类中,类可以调用同时实例化对象也可以调用,在类中属于全局变量 |
| |
| class N(object): |
| age = 18 |
| |
| def __init__(self, name): |
| self.name = name |
| |
| |
| n = N('zss') |
| print(n.age) |
| print(n.name) |
| print(N.age) |
| |
| |
| 优先去实例变量中找,找不到,去类变量找 |
| |
| 2.对类内部的变量进行添加与修改 |
| class N(object): |
| age = 18 |
| |
| def __init__(self, name): |
| self.name = name |
| |
| |
| n = N('zss') |
| n.name = '修改实例变量' |
| n.type = '添加一个实例变量' |
| |
| N.age = 999 |
| N.pee = '添加类变量' |
| |
| 通过 n.__dict__ 查看实例对象中全部的内容(只有__init__的变量) |
| 通过 N.__dict__ 查看类中的全部内容(不包过__init__的变量) |
| |
| 读:如果实例变量中没有,就去类变量中找 |
| 写:类添加和实例变量添加,不受影响,使用类名就是类添加变量,使用对象就是实例变量添加 |
| |
| |
| 2.成员修饰符 |
| |
| 公有:任何地方都可以调用 |
| 私有:只能在自己类中使用 |
| 定义:__双下划线定义 |
| class N(object): |
| |
| def __init__(self, name, age): |
| self.name = name |
| self.__age = age |
| |
| def __func(self): |
| pass |
| |
| def func2(self): |
| pass |
| |
| |
| n = N('zss', 18) |
| |
| |
| class N(object): |
| |
| def __init__(self, name, age): |
| self.name = name |
| self.__age = age |
| |
| def __func(self): |
| pass |
| 因为共有方法可以被外部调用,私有只能被内部调用,那么就使用外部调用内部 |
| def func2(self): |
| self.__func() |
| print(self.__age) |
| |
| |
| n = N('zss', 18) |
| n.func2() |
| |
| |
| 1.想要外部调用就是公有 |
| 2.想要内部成员只是作为辅助其他成员 就用私有 |
| 3.成员是否作为独立功能暴露给外部,让外部调用 |
| |
| |
| 3.外部硬执行私有方法变量 |
| 案例: |
| class foo: |
| |
| def __init__(self,a1,a2): |
| self.a1 =a1 |
| self.__a2 =a2 |
| |
| |
| def __f1(self): |
| pass |
| def f2(self): |
| self.__f1 |
| |
| obj = foo() |
| |
| print(obj._foo__a2) |
| |
| obj._foo__f1() |
3.使用类封装分页方法
| class Pagination: |
| |
| def __init__(self, current_page, per_pagr_num=10): |
| self.per_pagr_num = per_pagr_num |
| |
| if current_page.isdecimal(): |
| |
| self.current_page = 1 |
| return |
| |
| current_page = int(current_page) |
| |
| if current_page < 1: |
| |
| self.current_page = 1 |
| return |
| |
| self.current_page = current_page |
| |
| |
| @property |
| def start(self): |
| |
| return (self.current_page - 1) * self.per_pagr_num |
| |
| @property |
| def end(self): |
| |
| return self.current_page * self.per_pagr_num |
| |
| |
| |
| list = [1w数据] |
| if __name__ == "__main__": |
| while True: |
| page = input(">>>") |
| pa_object=Pagination(page,10) |
| list_object = list[pa_object.start:pa_object.end] |
| for i in list_object: |
| print(i) |
4.class的3大特征封装继承多态
1.封装
| 特征: |
| 封装,继承,多态 |
| |
| 1.封装 |
| |
| |
| |
| 分装的扩展性: |
| 使用者不需要知道内部的逻辑,只需要接口的怎么调用就可以 |
| 创建者,只需要将内部的逻辑编写完整,将需要暴露的外部接口暴露就可以 |
| 体现在两个方面 |
| 1.将同一类方法封装到类中 :西瓜和苹果都是水果类的 |
| 2.将数据封装到对象中,在实例化对象时,通过__init__初始化方法封装到实例化的对象中 |
| 便于以后使用 |
| 封装的体现: |
| class 信息: |
| def __init__(self,n1) |
| self.n1 = n1 |
| |
| def 发微信(self): |
| print(self.n1) |
| |
| def 发短信(self): |
| print(self.n1) |
| |
| def 发微博(self): |
| print(self.n1) |
| |
| 对象 = 信息(xxxxxxxxx) |
| 对象 = 信息() 将类中的方法 封装到对象中(变量),通过对象进行调用 |
| 对象.发短信()... |
| 1.对类进行实例化时 |
| 2.执行init方法,init的n1接受传入的值 |
| 3.在将数据封装到 init方法中 self.n1 = n1 |
| 4.在内存区域开辟一个 存储 n1 = n1的数据 |
| 5.对象 会成为参数传入到self的内存中 self内部就存储这信息类的方法和数据 |
| |
| |
| |
| |
| |
| |
| |
| 4.总结 |
| 总结: |
| 1.封装:将方法,数据封装到对象中,便于以后使用 |
| 2.继承:将功能中的公共方法放到父类中,让子类继承使用 |
| 3.多态:python参数是多态的,但是内部的方法是有约束的,只有相同的方法,才可以 |
2.继承
| 1.继承 |
| |
| 继承的作用:增加代码的复用性,类与类之间的关系,解决代码的冗余问题,重用性提高 |
| 两个类同时都有一个方法,那么可以将方法重新创建一个类,放另外两个类继承。 |
| |
| 子类可以继承父类的方法和类变量(数据)(不属于拷贝,父类的还是父类的,子类可以用) |
| class Base: |
| |
| def func(self): |
| pass |
| |
| class Son(Base): son类继承了 base类 |
| |
| def show(self): |
| pass |
| |
| class Func(Base): |
| pass |
| |
| son = Son() |
| son.show() |
| |
| func = Func() |
| func.show() |
| |
| |
| |
| |
| 类.__bases__ |
| 类名.mro() |
| |
| |
| 2.类的查询方法 |
| |
| 查找的方式: |
| 深度优先 和 广度优先 |
| |
| 只有在python2中 分为 新式类 和 经典类之分 |
| |
| 在python2中 子类和父类没有继承object类 |
| class A: |
| pass |
| |
| class B(A): |
| pass |
| |
| 在python2中继承了object类 被称为新式类 |
| class A(object): |
| pass |
| |
| class B(A): |
| pass |
| |
| |
| 在python3 默认基础object 都是新式类 |
| class A: |
| pass |
| |
| print(A.__bases__) |
| |
| 新式类与经典类查找顺序不同 |
| 经典类: 是深度优先 |
| 例如: |
| class A(B,C,D) |
| pass |
| 先从继承的B类开始一直找到B类的父类的尽头 |
| 在去继承的C类开始找找到C类父类的尽头 |
| 在去找继承D类父类的尽头 |
| |
| 新式类: 是广度优先 |
| 最深的继承的类不会先找,而是平行到相邻类中找,到最后在找最深的继承类 |
3.多态
| 3.多态 |
| 传入的数据类型多种形态的(参数时多种形态,传入的参数都必须要有同样的方法) |
| 方法是有约束的,参数时多态的任意类型,函数内部调用的方法规则 |
| 多态性是面向对象编程的又一个重要特征,它是指在父类中定义的属性和方法被子类继承之后,可以具有不同的数据类型或表现出不同的行为,这使得同一个属性或方法在父类及其各个子类中具有不同的含义 |
| |
| 值的是可以不在考虑对象的类型下而直接使用对象本身 |
| 增加程序的灵活性 |
| 增加程序的扩展性 |
| 鸭子类型: |
| 根本不用在乎多种类型的使用 |
| 例如: |
| 开车,只要学会开车,那么全部的类型车就可以开(奥迪....) |
| |
| 鸭子类型: |
| 比如: |
| 不让子类继承父类(强制的abc.ABCMeta抽象类) |
| 而是让子类模拟父类 |
| |
| 代码比喻: |
| 文件类型类 有读 和写文件 |
| class File: |
| def read(slfe): |
| pass |
| def write(self): |
| pass |
| |
| class Disk: |
| def read(slfe): |
| pass |
| def write(self): |
| pass |
| |
| class Text: |
| def read(slfe): |
| pass |
| def write(self): |
| pass |
| |
| def func(obj): |
| obj.read() |
| |
| 他们有都是由两个方式 read 和 write 两种方式 |
| text = Text() |
| disk = Disk() |
| |
| |
| |
| text.read() |
| disk.read() |
5.super的用法
| 也就是,当自己类中派生的存在,那么就是用自己的,不在使用父类的属性 |
| 现在对象中的找对象的命名空间中,在从对象当前类中的找,在去父类中找 |
| |
| |
| class A: |
| |
| def __init__(self): |
| pass |
| |
| def show(self): |
| print(123) |
| class Func(A): |
| name = 123 |
| |
| def show(self): |
| print(456) |
| |
| f = Func() |
| f.show() 那么他就是还是用自己的类中的show方法 |
| |
| |
| |
| ******* 在子类中重用父类的属性 ***** |
| |
| class A: |
| |
| def __init__(self, name): |
| self.name = name |
| |
| def show(self, age): |
| print(123) |
| |
| |
| class B(A): |
| |
| |
| |
| |
| def __init__(self,name,age) |
| A.__init__(self,name) |
| self.age = age |
| |
| |
| def show(self, age): |
| |
| A.show(self, age) |
| print(4456) |
| |
| b = B('123') |
| b.show(666) |
| |
| |
| ******** super() ********** |
| 2. 第二种情况子类需要有自己的初始化方法,进行对象的独特的值 |
| 使用super可以 对象的方式进行调用父类的中的方法 |
| 使用 super() 依赖继承 具体依赖是那个类的实例化对象,他存在的mro继承关系,而不是取决于super() 存在那个类 |
| |
| class A: |
| |
| def __init__(self, name): |
| self.name = name |
| |
| def func(self): |
| print(123) |
| |
| |
| |
| |
| class B(A): |
| def __init__(self, name, age): |
| |
| |
| |
| super().__init__(name) |
| self.age = age |
| def show(self): |
| |
| super(B, self).func() |
| |
| |
| b = B('HAHA',18) |
| b.show() |
6.抽象类
| python 提供了抽象类的概念,提供了一个接口的方式 |
| 模仿java 模仿 interface接口 |
| |
| 抽象类:将全部的类抽取比较像的部分,形成一个父类,让子类继承父类必须使用当前的父类的方法,必须让继承父类的子类必须按照父类的规定进行使用 |
| |
| |
| import abc |
| |
| |
| |
| |
| |
| |
| |
| class Animal(metaclass=abc.ABCMeta): |
| @abc.abstractmethod |
| def run(self): |
| pass |
| |
| @abc.abstractmethod |
| def eat(self): |
| pass |
| |
| |
| |
| |
| class People(Animal): |
| |
| def run(self): |
| print('people') |
| |
| def eat(self): |
| pass |
| |
| 凡是继承当前抽象类,那么必须定义父类中的定义的方法,那怕不实现也可以 |
进阶使用
1.类中的3种方法
| 1.绑定方法 __init__(self)方法 :对象调用 |
| 默认参数时self,self代指实例对象,内部存放着类的方法和实例变量/类变量 |
| |
| 2.类方法 @classnethod :类名调用 |
| 默认参数 cls ,cls就是代指这整个类。作用:在方法内部使用 类 就用类方法 |
| |
| 3.静态方法 @staticmethod :类名调用 |
| 无默认参数,作用:如果方法内部只是一些简单的逻辑,不适用参数,就可以使用静态方法 |
| |
| 使用方式案例: |
| class foo: |
| |
| def __init__(self): |
| pass |
| |
| |
| def show1(self): self 指向 实例对像 a |
| pass |
| |
| @classmethod |
| def show2(cls): |
| pass |
| |
| @staticmethod |
| def show3(): |
| pass |
| |
| a = foo() |
| a.show1() |
| foo.show2() |
| foo.show3() |
| |
| |
| 绑定方法的特殊 |
| |
| 1.使用类名进行调用内部的方法函数时,需要对应的传入指定的位置参数self |
| 而且类名调用的方法函数,就是一个普通的函数 |
| |
| 2.绑定方法是给实例化对象使用,绑定不同的对象效果也是不同的 |
| 而对象调用内部的方法函数时,默认自动将对象本身传入到方法函数中的self中 |
| 也就是 a1.learn(a1) 将对应本身默认传入参数 |
| |
| 总结:对象来调用自己内部的绑定方法时,会将对象本身当为第一个参数(self)传入到方法中 |
| 剩余的参数,该怎么传入就怎么传入 |
| |
| 类中的方法函数,是给对象使用,那个对象来调用,就将他当为第一个参数传入 |
| |
| 如果对象的名称空间中这个参数存在,那么就是用对象的名称空间中的 |
| 如果名称空间中的参数不存在,就会使用类中的参数 |
| |
| 和函数中的局部和全局的概念是相同的意思 |
| 如果对象名称空间(局部)不存在的,那么就使用类空间中的(全局的) |
| 当找不到也不会去类外部找 |
| |
| 绑定方法 如果用类名调用内部的方法是不同函数 用对象调用方法是绑定函数 同时他们的内存地址是不同的 |
| |
| |
2.类中的三个特殊属性property
| 属性是由绑定方法和装饰器组成的。 |
| |
| class Func: |
| |
| @property |
| def func1(self): |
| print('执行property') |
| |
| |
| @func1.setter |
| def func2(self, val): |
| print(val) |
| |
| |
| @func1.deleter |
| def func3(self): |
| print('deleter') |
| |
| |
| a = Func() |
| a.func1 |
| a.func2 = 123 |
| del a.func3 |
| |
| 方法1: |
| 定义规则:@方法名.setter,方法中需要多加一个value参数 |
| 使用方式:a.func2 = 123 参数value可以接受 添加的值 |
| |
| 方法2: |
| 定义规则:在方法上加入:@property |
| 使用方法:a.func 在调用方法时可以不用加括号 |
| |
| 方法3: |
| 定义规则:@方法名.deleter |
| 使用方式:del a.func3 执行方法 |
3.类中的其他方法内置1
| class Func: |
| |
| |
| |
| def __init__(self, name): |
| self.name = name |
| |
| |
| def __new__(cls, *args, **kwargs): |
| |
| return object.__new__(cls) |
| |
| |
| def __str__(self): |
| return "这是一个不同的方法类" |
| |
| |
| |
| @property |
| def __dict__(self): |
| return '7788' |
| |
| ''' |
| 例如: |
| class A: |
| def __init__(self,a1,a2): |
| self.a1 =a1 |
| self.a2 =a2 |
| A = A(11,12) |
| print(A.__dict__) # {'a1': 11, 'a2': 12} |
| ''' |
| |
| a = Func('zzz') |
4.类方法其他方法内置2
| class Func: |
| |
| def __call__(self, *args, **kwargs): |
| print(args, kwargs) |
| return '110' |
| |
| |
| a = Func() |
| print(a('666', '777')) |
| |
| call 作用使实例化对象需要加括号进行调用执行的方法 |
| 当实例对象('可以传入参数') 就会直行call方法,不会影响类中的其他方法调用 |
5.类方法其他方法3
| 字典支持 对象["xx"]取值 对象["xx"] =123 赋值 del 对象["xx"] 删除键值对 |
| |
| __setitem__ __getitem__ __delitem__ |
| |
| class Func: |
| |
| def __setitem__(self, key, value): |
| '''字典赋值操作''' |
| print(key, value) |
| |
| def __getitem__(self, item): |
| '''字典get操作''' |
| print(item) |
| |
| def __delitem__(self, key): |
| '''字典的删除操作''' |
| print(key) |
| |
| |
| a = Func() |
| a['666'] = 777 |
| a['666'] |
| del a['666'] |
| |
| 当时实例对象按照字典形式执行方式时 会触发当前三个方法 |
6.类方法其他方法4
| 让对象支持with 上下文语法 执行 |
| |
| class Func: |
| |
| def __enter__(self): |
| return '测试执行中' |
| |
| def __exit__(self,*args,**kwargs): |
| print('执行结束') |
| |
| |
| a = Func() |
| |
| with a as e: |
| print(e) |
| |
| ''' |
| 1.先执行__enter__方法 返回值赋值给e |
| 2.执行完毕__enter__方法才会执行 __exit__方法 |
| ''' |
| |
| |
| 让两个实例对象进行加减 |
| |
| class A(): |
| |
| def__add__(self,other): |
| return |
| |
| a = A() |
| a1= A() |
| |
| v3 = a+a1 |
| |
7.类方法其他方法5
| 迭代器的定义: |
| 1.在定义类 中 必须有__iter__ 和__next__两个方法 |
| 2.__iter__ 返回对象本身 就是 self,将self返回 |
| 3.__next__ 返回下一个数据,没有数据就执行 stopiteration异常 |
| |
| 迭代器的定义: |
| 1.在定义类 中 必须有__iter__ 和__next__两个方法 |
| 2.__iter__ 返回对象本身 就是 self,将self返回 |
| 3.__next__ 返回下一个数据,没有数据就执行 stopiteration异常 |
| |
| |
| 迭代器类 |
| |
| class A(object): |
| |
| def __init__(self): |
| self.count = 0 |
| |
| def __iter__(self): |
| return self |
| |
| def __next__(self): |
| self.count +=1 |
| if self.count == 3: |
| raise stopiteration() |
| return self.count |
| |
| |
| |
| a = A() |
| |
| v1 = next(a) 1 |
| v2 = next(a) 2 |
| v3 = next(a) 抛出异常 |
| |
| for i in a : |
| print(i) |
| |
| |
| |
| |
| |
| |
| |
| |
| 生成器 |
| 生成器属于迭代器的一种 |
| def func(): |
| yield 1 |
| |
| |
| |
| |
| |
| |
| |
| |
| 可迭代对象 |
| |
| class A(object): |
| |
| def __iter__(self): |
| return |
| |
| a = A() |
| |
| |
| |
| for i in a : |
| pass |
| |
| 可迭代对象和迭代器组合 |
| |
| class A(object): |
| |
| def __init__(self): |
| self.count = 0 |
| |
| def __iter__(self): |
| return self |
| |
| def __next__(self): |
| self.count +=1 |
| if self.count == 3: |
| raise stopiteration() |
| return self.count |
| |
| class A1(object): |
| |
| def __iter__(self): |
| return A()可迭代对象 |
| |
| for i in A1(): |
| print(i) |
8.类中的内置方法总结
| 1.@classmethod 类方法 参数cls |
| 2.@staticmethod 静态方法 无参数 |
| 3.@property 在执行类中的方法时不用加括号 |
| 4.callable(函数名) 判断执行对象是否后面可以加括号 |
| 5.super() 按照mro的方法向上找到父类成员关系(优先取找父级的方法) 如果父类没有,就会报错 |
| 6.type ,获取对象的类型 |
| 7.isinstance(实例化对象,父类) 判断对象是不是某个类的继承或者子类 返回True/False |
| 8.issubclass() 判断是否是类的子孙类 返回True/False |
9.类使用嵌套
| class student(object): |
| |
| def __init__(self,name,age): |
| self.name = name |
| self.aeg = age |
| |
| def messaage(self): |
| data = "{},{}".format(self.name ,self.aeg) |
| print(data) |
| |
| |
| class classes(object): |
| |
| def __init__(self,title): |
| self.title = title |
| self.student_list = [] |
| |
| def add_student(self,stu_object): |
| self.student_list.append(stu_object) |
| |
| def add_students(self,stu_object_list): |
| for i in stu_object_list: |
| self.add_student(i) |
| |
| def show_members(self): |
| for i in self.student_list: |
| print(i) |
| |
| s1 = student("123",12) |
| s2 = student("4565",13) |
| c1 = classes("年级") |
| c1.add_student(s1) |
| c1.add_students([s1,s2]) |
| |
| |
| |
| |
| |
| |
| class A(object): |
| |
| def __init__(self,name,aeg,class_object): |
| self.name = name |
| self.age = aeg |
| self.class_object = class_object |
| def message(self): |
| data = "{},{},{}".format(self.name,self.age,self.class_object) |
| print(data) |
| |
| class B(object): |
| |
| def __init__(self,title): |
| self.title = title |
| |
| |
| b =B("python全站") |
| b2 = B("linux云计算") |
| |
| a = A("wkx","18",b.title) |
| a2 = A("wyx","16",b2.title) |
| a.message() |
| a2.message() |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| class A(object): |
| |
| def __init__(self,name,aeg,class_object): |
| self.name = name |
| self.age = aeg |
| self.class_object = class_object |
| def message(self): |
| data = "{},{},{}".format(self.name,self.age,self.class_object) |
| print(data) |
| |
| class B(object): |
| |
| def __init__(self,title,C_object): |
| self.title = title |
| self.C_object = C_object |
| |
| class C(object): |
| |
| def __init__(self,name): |
| self.name = name |
| |
| s1 = C("上海") |
| s2 = C("北京") |
| |
| c1 = B("全站",s1) |
| c2 = B('云计算',s2) |
| |
| user_list = [ |
| A("123","18",c1), |
| A("123","18",c2) |
| ] |
| |
| for i in user_list: |
| print(i.name,i.age,i.class_object.title,i.class_object.C_object.name) |
| |
| |
| |
| |
| |
| |
| |
10.mro与c3算法确定类的基础关系
| 子类没有去找父类 |
| 利用方法知道父类关系 |
| mro():作用于找到父类关系 |
| 类.mro() 返回一个列表 类关系 |
| 类.__mro__ 返回一个元组 类关系 |
| 底层原理 : c3 算法 |
| 规则: |
| mro(A) = [A]+(b,c) |
| mro(A) = [A,B,C] |
| |
| 使用方式: |
| |
| mro(A) = [A]+merge(mro(B,object),mro(C,object,D,object,E,object),[B,C,D,E]) |
| 重点 |
| 1.从merge(第一个mro(元素1))对比merge(第二个mro(元素2)) 是否存 |
| 2.不存在剔除掉 |
| 3.在从merge(第一个mro(元素1))对比merge(第二个mro(元素2)) 是否存在 |
| 4.存在,保留,从merge(第二个mro(元素1)) 取其他的作为比较,不存在剔除。再从第一个mro第一个元素进行匹配 |
| |
| 继承关系: |
| 继承关系:从左到右,深度优先。大小钻石,留住顶端。 |
| 钻石继承: |
| -------D------ |
| B--------------C |
| -------A------- |
| A-B-C-D |
11.元类
| |
| |
| |
| |
| |
| g = { |
| 'x': 10, |
| 'y': 20 |
| } |
| |
| l = {} |
| |
| |
| |
| |
| |
| exec(''' |
| global x,mxxxx |
| x=100 |
| mxxxx = 1000 |
| z=30 |
| |
| ''', g, l) |
| |
| |
| |
| |
| |
| ****** python 中一切皆对象 ***** |
| 1.都可以被引用 x = obj |
| 2.都可以当成函数的参数传入 |
| 3.都可以作为函数返回值 |
| 4.都可以当做容器的元素 [obj.....] |
| |
| |
| |
| 默认用class定义的类,他们的原类都是type |
| |
| class A: |
| pass |
| |
| a = A() |
| print(type(a)) |
| print(type(A)) |
| |
| |
| |
| 1.class定义 |
| 2.type定义 |
| 定义类的三要素 |
| 1.类名 |
| 2.类继承的父类 |
| 3.类的名称空间 |
| |
| |
| class_name = 'A' |
| class_bases = (object,) |
| calss_boby = ''' # 声明使用type声明类的中的方法 |
| def __init__(self,name): |
| self.name = name |
| def func(self): |
| pass |
| ''' |
| class_dic = {} |
| exec(calss_boby, globals(), class_dic) |
| |
| A = type(class_name, class_bases, class_dic) |
| |
| print(class_dic) |
| print(A.__dict__) |
| |
| |
| ****** 自定义元类 控制类的创建 ******* |
| |
| class Mymeta(type): |
| |
| |
| |
| def __init__(self, class_name, class_bases, class_dic): |
| print(class_dic) |
| print(class_name) |
| print(class_bases) |
| if not class_name.istitle(): |
| raise TypeError('类名首字母大写') |
| if '__doc__' not in class_dic or not class_dic['__doc__'].strip(): |
| raise TypeError('必须有注释,并且不能为空') |
| |
| |
| super().__init__(class_name, class_bases, class_dic) |
| |
| |
| |
| |
| class Chinese(object,metaclass=Mymeta): |
| '''000''' |
| country = 'China' |
| |
| def __init__(self): |
| pass |
| |
| def func(self): |
| pass |
| |
| |
| ''' |
| |
| print(class_dic) |
| print(class_name) |
| print(class_bases) |
| 打印的内容 |
| {'__module__': '__main__', |
| '__qualname__': 'A', '__init__': <function A.__init__ at 0x000001B480CFE3A0>, |
| 'func': <function A.func at 0x000001B480D17040>} # 类的方法 |
| A 类名 |
| (object) # 继承的父类类 |
| ''' |
| |
| |
| ****** 定于元类 控制类的实例化 ****** |
| |
| 补充 |
| |
| |
| class F: |
| |
| |
| def __call__(self, *args, **kwargs): |
| print(self) |
| print(args) |
| print(kwargs) |
| |
| |
| f = F() |
| |
| f(1,a=12) |
| |
| |
| 自定义原类,并且初始化过程模拟 |
| |
| class Mymeta(type): |
| |
| def __init__(self, class_name, class_bases, class_dic): |
| print(class_name) |
| if not class_name.istitle(): |
| raise TypeError('类名首字母大写') |
| if '__doc__' not in class_dic or not class_dic['__doc__'].strip(): |
| raise TypeError('必须有注释,并且不能为空') |
| |
| super().__init__(class_name, class_bases, class_dic) |
| |
| def __call__(self, *args, **kwargs): |
| |
| |
| |
| 初始化过程 |
| |
| |
| obj = object.__new__(self) |
| |
| |
| self.__init__(obj, *args, **kwargs) |
| |
| return obj |
| |
| |
| class Chinese(object, metaclass=Mymeta): |
| '''000''' |
| country = 'China' |
| |
| def __init__(self, name, age): |
| self.name = name |
| self.age = age |
| |
| def func(self): |
| pass |
| |
| |
| |
| |
| |
| obj = Chinese('wkx', 18) |
| |
| ''' |
| 实例化过程 |
| 1.创建空对象 |
| 2.初始化obj |
| 3.返回obj |
| |
| 而元类的过程也是一模一样的 |
| ''' |
| print(obj.__dict__) |
| |
| |
| |
| ******* 使用创建的元类进行实例化应用 ******* |
| |
| |
| class M: |
| __instance = None |
| |
| def __init__(self): |
| pass |
| |
| @classmethod |
| def singleton(cls): |
| if not cls.__instance: |
| obj = cls() |
| cls.__instance = obj |
| return cls.__instance |
| |
| |
| a = M.singleton() |
| b = M.singleton() |
| print(a is b) |
| |
| |
| |
| |
| |
| |
| class Mymeta(type): |
| |
| def __init__(self, class_name, class_bases, class_dic): |
| print(class_name) |
| if not class_name.istitle(): |
| raise TypeError('类名首字母大写') |
| if '__doc__' not in class_dic or not class_dic['__doc__'].strip(): |
| raise TypeError('必须有注释,并且不能为空') |
| |
| super().__init__(class_name, class_bases, class_dic) |
| |
| self.__instance = None |
| |
| def __call__(self, *args, **kwargs): |
| if not self.__instance: |
| obj = object.__new__(self) |
| self.__init__(obj, *args, **kwargs) |
| self.__instance = obj |
| |
| return self.__instance |
| |
| |
| class M(object, metaclass=Mymeta): |
| '''1''' |
| def __init__(self): |
| pass |
| |
| |
| m = M() |
| m1 = M() |
| print(m is m1) |
| print(type(M)) |
异常处理与反射
1.异常处理
| 1.处理原理: |
| 1.基本格式 |
| try: |
| 正常逻辑代码 |
| except Exception as e: |
| e 是一个对象 内部存放的错误信息 可以通过str进行转换 |
| |
| |
| 2.高级格式 |
| try: |
| 正常逻辑代码 |
| |
| except Exception as e: |
| try内的代码异常触发,此处代码。 |
| |
| finally: |
| try中的代码是否报错,finally的代码都会执行。被成为释放资源 |
| |
| |
| 2.异常处理的细分 |
| try: |
| 正常逻辑代码 |
| except 其他异常 as e: |
| 代码 |
| except 其他异常 as e: |
| 代码 |
| except 其他异常 as e: |
| 代码 |
| except Exception as e: 捕获全部的异常 |
| try内的代码异常触发,此处代码。 |
| |
| 3.自定义异常类 |
| |
| class 自定义异常类名(继承Exception类): |
| pass 代码 |
| |
| try: |
| 正确的逻辑代码 |
| |
| raise 自定义议程类名() |
| except 类名 as e: |
| 当出现异常就会创建一个异常类的对象 赋值给 e ,e自定义异常类的对象 |
| 可以将e获取错误 |
| finally |
| 在函数内定义finally无论遇到return 都会返回finally内的代码 |
| |
| |
| 案例: |
| |
| class MyException(BaseException): |
| |
| def __init__(self,msg): |
| super().__init__() |
| self.msg = msg |
| def __str__(self): |
| return self.msg |
| |
| raise MyException('抛出自己的错误') |
补充
| raise参数的作用:显示与引发异常的作用 |
| 当程序出现错误时,python自动触发异常,也可以使用raise进行触发异常 |
| 一旦raise触发异常后,python后面的代码就不在执行 |
| 如果加入了try,except,那么except里面的语句会被执行 |
| |
| try是捕获异常,当raise触发异常时,就会触发except的异常报错 |
| 例如: |
| try: |
| s = None |
| if s is None: |
| print('s是空对象') |
| raise NameError |
| print(len(s)) |
| |
| except Exception: |
| print('空对象没有长度') |
2.反射
| 反射:支持以字符串的行式取操作成员 执行getattr |
| 反射的使用方式: |
| class A : |
| def __init__(self,a): |
| self.a = a |
| |
| def show(self): |
| pass |
| a1 = A() |
| |
| v1 = getattr(a1,“a”) 等价与 a1.a |
| |
| |
| v1 = getattr(a1,“show”,none)() 等价与 a1.show() |
| |
| |
| |
| 1.添加成员变量 |
| setattr(a1,“b”,“值”) |
| |
| 2.判断成员是否存在 |
| v1 = hasattr(a1,“a”) |
| print(v1) |
| |
| 3.删除成员 |
| delattr(a1,“a”) |
| |
| |
| |
| |
| |
| 1.导入模块 |
| from importlib import import_module |
| |
| 2.使用模块名 |
| 对象 = import_module("模块名称") |
| |
| |
| 3.使用方法 |
| getattr(对象,模块的方法) |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步