? 面向对象的优点:
? 1.对相似功能的函数,同一个业务下的函数进行归类,分类
? 2.类是一个公共的模板,对象就是从具体的模板中实例化出来的,得到对象就得到一切
类:具有相同属性和功能的一类事物
对象:某个类的具体表现
2.面向对象的结构class Human:#类名不要用下划线 #第一部分:静态属性 mind = '有思想' #类的属性 (静态属性,静态字段) #第二部分:动态方法 def eat(self):#方法 print('人类都需要吃饭')3.从类名的角度研究类 1.类名查看类中所有的内容
print(Human.__dict__)#结果:#{'__module__': '__main__','mind': '思想','eat': <function Human.eat at 0x000001AD41659D08>,'__dict__': <attribute '__dict__' of 'Human' objects>,'__weakref__': <attribute '__weakref__' of 'Human' objects>,'__doc__': None}2.类名 *** 作类中的静态属性 (万能的点)
? 1.增:
Human.body = '有躯体'print(Human.__dict__)
? 2.删:del Human.mind
del Huamn.mind
? 3.改:Human.mind = ‘live脑残‘
Human.mind = 'live脑残'
? 4.查:print(Human.mind)
print(Human.mind)3.类名调用类中的方法
? 一般类中的(除了静态方法和类方法)方法不会通过类名调用
Human.eat(1)#self,需要传参,对象不需要,默认传对象名4.从对象的角度研究类 1.实例化对象:
obj = Human()#实例化过程#得到一个返回值,返回值就是对象,实例2.实例化一个对象发生三件事:
? 1.开辟一个对象空间。
? 2.自动执行object中的__new__()方法,在内存中开辟一个对象空间.
? 3.运行__init__方法内的代码,给对象空间封装属性
class Human: mind = '有思想' def __init__(self,name,age): self.name = name self.age = age def eat(self): print('人类都需要吃饭')obj = Human()#将obj传给了self,自动执行__init__()函数print(obj)#结果:<__main__.Human object at 0x00000210B6A48E80>#传参:obj = Human('qq',18)print(obj.name,obj.age)'''结果:qq 18'''print(obj.__dict__)#对象的属性,字典的形式'''结果:{'name': 'qq','age': 18}'''3.对象 *** 作对象空间的属性 1.对象查看对象空间的所有属性:
? 1.print(obj.__dict__):
obj = Human('qq',18)print(obj.__dict__)2.对象 *** 作对象空间的属性
? 1.增:obj.sex = ‘laddy_boy‘
? 2.删:del obj.age
? 3.改:obj.age = 58
? 4.查:print(obj.sex)
4.对象查看类中的属性? 对象不允许修改类中的属性,只允许查看。
obj = Human('qq',18)print(obj.mind)#通过对象查看类中的属性obj.mind = '无脑'print(obj.mind)print(Human.mind)'''类中的属性并没有更改,而是对象中新增了mind属性'''5.对象调用类中的方法
class Human: mind = '有思想' def __init__(self,age): self.name = name self.age = age def eat(self): print(f'{self.name}都需要吃饭') def work(self): print(f'{self.name}都会工作')obj = Human('戴维',23)obj.work()obj.eat()6.一个类可以实例化多个对象
obj1 = Human('戴维',20)obj2 = Human('杰西',22)obj3 = Human('肉丝',18)5.类的空间问题
? 1.添加对象的属性
#1.在类的__init__中添加,#2.在类的方法中添加def eat(self,argv): self.sex = '女'#3.在类的外部添加sun = Human('孙','18')sun.weight = 120
? 2.添加类的属性
#1.类的内部,直接定义#2.类的外部:Human.body = '有头有脸'
? 3.对象空间与类空间的关系
当对象空间与类空间有相同的的名字,对象. 要先从对象空间查找
查询顺序:
对象.名字:对象空间 _类对象指针_ -->类空间 -- >父类空间
类名.名字:类空间 --> 父类空间
6.类与类之间的关系 1.依赖关系:? 有主从之分,将一个类的类名或者对象传入另一个类的方法中
class Elephant:#主 def __init__(self,name): self.name = name def open(self,obj): print(f'{self.name}打开冰箱') obj.be_open()class Fire:#从 def __init__(self,name): self.name = name def be_open(self): print(f'{self.name}冰箱被打开了') qiqi = Elephant('琪琪')haIEr = Fire('海尔')qiqi.open(haIEr)'''结果:琪琪打开冰箱海尔冰箱被打开了'''2.组合关系:
? 给一个类的对象封装一个属 性,此属性为另一个类的对象(类名)
class Game: def __init__(self,ad,hp): self.name = name self.ad = ad self.hp = hp def attrck(self,p): ''' 2. #p.hp = p.hp - self.ad - self.weap.a d #print(f'{self.name}使用{self.weap.name}攻击{p.name},掉了{self.ad+self.weap.ad},还剩{p.hp}') ''' def equipment(self,weap): self.weap = weapclass Weapon: def __init__(self,ad): self.name = name self.ad = ad def weappon(self,p1,p2): #1. p2.hp = p2.hp - p1.ad - self.ad #1. print(f'{p1.name}使用{self.name}攻击{p2.name},{p2.name}掉了{p1.ad+self.ad}血量,{p2.name}还剩{p2.hp}')gailun = Game('盖伦',10,100)zhaoxin = Game('赵信',20,80)baojian = Weapon('大宝剑',20)changqiang = Weapon('长q',15)#1. gailun.equipment(baojian)# 1.gailun.weap.weappon(gailun,zhaoxin)# 1.zhaoxin.equipment(changqiang)# 1.zhaoxin.weap.weappon(zhaoxin,gailun)'''2.gailun.equipment(baojian)gailun.attrck(zhaoxin)gailun.attrck(zhaoxin)'''7.继承 1.初识继承:
? 专业角度:如果B类继承A类,B类就称为子类、派生类。A类就称为父类、基类、超类。
? 面向对象三大特性:封装、继承、多态
最顶级父类就是object
2.继承的优点:? 1.减少重复代码
? 2.增加类之间的耦合性
? 3.使代码更加清晰,流畅
3.继承:单继承,多继承 1.单继承:? 查询顺序单项不可逆:子类可使用父类的属性方法,父类不可使用子类的属性方法
? 1.1 类名执行父类属性方法,对象执行父类属性方法
class Animal: def __init__(self,sex,age): self.name = name self.sex = sex self.age = ageclass Human(Animal): passclass Dog(Animal): passclass Cat(): pass#Animal:父类#Human,Dog:子类person = Human('C罗','男',18)#cat1 = Cat()#默认为继承object
1.2 既执行子类的方法,又执行父类的方法
方案一:不依赖于继承,使用函数的调用
方案二:依赖于继承。super(),
执行父类的方法。称为重构
class Animal: def __init__(self,age): self.name = name self.sex = sex self.age = age pass def eat(self): print('动物都需要吃饭')class Human(Animal): def __init__(self,age,hobdy): #方案一 #Animal.__init__(self,age)#需要传入人类对象,姓名,性别,年龄 #方案二: #super(Huamn,self).__init__(name,age)#完整写法 super().__init__(name,age)#简写 self.hobdy = hobdy pass def eat(self): super().eat() print(f'{self.name}需要吃饭')human1 = Human('涛涛','雌','48','唱跳')print(human1.__dict__)human1.eat()'''结果:{'name': '涛涛','sex': '雌','age': '48','hobdy': '唱跳'}动物都需要吃饭涛涛需要吃饭'''2.多继承:
python中类分为两种:
python2.x:python 2.2之前都是经典类,python2.2之后,经典类与新式类共存
python3.x:全是新式类
? 1.经典类:不继承object类,遵循深度优先原则:从左至右。
? 2.新式类:继承object类,遵循mro(C3)算法
关于mro算法:
mro序列:class B(A): passmro(B) = mro(B(A)) = [B] + merge(mro(A) + [A]) = [B,A]表头和表尾
表头:列表的第一个元素
表尾:列表中除表头以外的所有元素(可以为空)
+ *** 作:[A] + [B] = [A,B]
merge规则:如计算merge( [E,O],[C,E,F,[C] )有三个列表 : ① ② ③1 merge不为空,取出第一个列表列表①的表头E,进行判断 各个列表的表尾分别是[O],[E,O],E在这些表尾的集合中,因而跳过当前当前列表2 取出列表②的表头C,进行判断 C不在各个列表的集合中,因而将C拿出到merge外,并从所有表头删除 merge( [E,[C]) = [C] + merge( [E,O] )3 进行下一次新的merge *** 作 ......mro算法实例:print(A.mro())
class O: name = 'qq'class D(O): passclass E(O): name = 'wx' # passclass F(O): name = 'taobao'class B(D,E): passclass C(E,F): passclass A(B,C): passobj = A()print(obj.name)print(A.mro())#直接得出mro算法求出的顺序"""mro(A(B,C)) = [A] + merge(mro(B),mro(C),[B,C])#多继承mro(B(D,E)) = [B] + merge(mro(D),mro(E),[D,E])#单继承:mro(D(O)) = [D,O] = [B] + merge([D,E])#拿出并删除D = [B,D] + merge([O],[E]) = [B,D,E] + merge([O],[O]) = [B,O] mro(C(E,F)) = [C] + merge(mro(E),mro(F),F]) = [C] + merge([E,[F,F]) = [C,[F]) = [C,F] + merge([O],[O]) = [C,O] mro(A(B,C)) = [A] + merge([B,C]) = [A,B] + merge([D,[C]) = [A,B,D] + merge([E,C] +merge([O],O]) = [A,C,O]所以:mro()算法得出的顺序为:A-->B-->D-->C-->E-->F-->O"""8.封装、多态和鸭子类型
? 1.封装:把数据代码放到一个空间,并且可以使用(函数)
? 2.多态:一个事物可呈现多种形态
python默认支持多态,一个变量可以指向多种数据类型
鸭子类型:python崇尚鸭子类型(编程思路),看起来像,就是鸭子。对相同的功能定义相同的名字。
鸭子的优点:
? 1.好记
? 2.虽然A,B两个类没有关系,但是统一两个类中相似方法的方法名,在某种意义上统一标准
class A: def login(self): print('登录')class B: def login(self): print('登录')'''A,B互为鸭子。'''9.类的约束
方法一:python语言惯于使用的一种约束方式,在父类主动抛出错误
class Payment: def pay(self): raise Exception('你的子类未定义pay方法')#主动报错,起到约束作用 class QQ_pay(Payment): def pay(self,money): print(f"QQ成功支付{money}元") class Ali_pay(Payment): def pay(self,money): print(f"支付宝成功支付{money}元") class Wechat(Payment): def fukuan(self,money): print(f"微信成功支付{money}元")def pay(obj,money):#归一化设计:统一接口 obj.pay(money) pass#使用Wechat实例化对象并调用pay函数,就会主动报错。
方法二:借鉴于java语言,定义抽象类的概念,做到真正的强制约束
from abc import ABCMeta,abstractmethod#抽象类,接口类:强制制定规则class Paymet(Metaclass=ABCMeta):#指定元素 @abstractmethod def pay(self,money): passclass QQ_pay(Paymet): def pay(self,money): print(f"QQ成功支付{money}元")class Wechat(Paymet): def fukuan(self,money): print(f"微信成功支付{money}元")def pay(obj,money): obj.pay(money)obj = Wechat()'''在实例化对象时就会报错 obj = Wechat()TypeError: Can't instantiate abstract class Wechat with abstract methods pay'''10.super的深度剖析
严格按照对象从属于类的mro的执行顺序执行,查询下一个类
class A: def f1(self): print('in A')class Foo(A): def f1(self): super().f1() print('in Foo')class bar(A): def f1(self): print('in bar') # 1class Info(Foo,bar): def f1(self): super(Foo,self).f1() print('in Info f1') # 2# [Info --> Foo --> bar --> A]obj = Info()obj.f1()11.类的关于 1.类的私有成员:
? 在类的内部可以访问,外部不可访问,也不可在类的派生类中使用。
? 当遇到重要的数据,功能,(只允许本类使用的)使用私有成员
类的私有成员:类的私有属性、类的私有方法、对象私有属性
class A: name = '涛涛' __name = '套套' def func(self): print(self.name) print(self.__name)obj = A()obj.func()#可以访问obj.__name#不可访问,会报错#如何访问私有属性:print(A.__dict__)#{'__module__': '__main__','name': '涛涛','_A__name': '套套','func': <function A.func at 0x00000237FC0F9D08>,'__dict__': <attribute '__dict__' of 'A' objects>,'__weakref__': <attribute '__weakref__' of 'A' objects>,'__doc__': None}##会发现私有属性都被加上了'_类名+私有名'#所以调用print(A._A__name)2.实例方法、类方法
1.实例方法:默认参数为self的方法
2.类方法:
? 一般就是通过类名去调用的方法,并且自动将类名地址传给cls,但是如果通过对象调用也可以,但传的地址还是类名地址
类方法作用:
? 1.得到类名可以实例化对象。
? 2.可以 *** 作类的属性
class A: @classmethod def cls_func(cls): print(f'cls'--->{cls}) #实例化对象 obj = cls() print(obj)print(A)A.cls_func()obj1 = A()obj.cls_func()3.静态方法:
? 静态方法不依赖对象与类。静态方法就是函数
作用:保证代码的规范性,合理的划分,提高代码后续维护性。
class A: @staticmethod def static_func(): print('静态方法')4.属性:
将执行一个函数需要函数名()变成直接函数名,将动态方法伪装成一个属性,虽然代码级别上没有提升,但是使其看起来更合理(本质还是方法)
class Bmi: def __init__(self,height,weight): self.name = name self.height = height self.weight = weight @property def bmi(self): self.BMI = self.weight / self.height**2 print(self.BMI)p1 = Bmi('w',1.75,74)p1.bmi
property是一个组合:
? 应用场景:1.面试考调用流程
? 2.工作中如果遇到一些类似属性的方法名,可以让其伪装成属性
设置属性的两种方式:后两个return是无效的,得不到。
1.利用装饰器设置属性
class Foo: @property def bmi(self): print('get的时候运行我') @bmi.setter def bmi(self,value): print('set的时候运行我') print(value)#return得不到 @bmi.deleter def bmi(self): print('delete时运行我') obj = Foo()obj.bmiobj.bmi = 666#不是改变值,而是调用@bmi.setter装饰下的函数del obj.bmi
2.利用实例化对象的方式设置属性
class Foo: def get_A(self): print('get的时候运行我') def set_A(self,value): print('set的时候运行我') print(value) def delete_A(self): print('delete的时候运行我') A = property(get_A,set_A,delete_A)#内置三个参数,与get,set,delet一一对应f1 = Foo()f1.Af1.A = '666'del f1.A5.内置函数:isinstance,issubclass
isinstance:判断的是对象与类的关系True/False
isinstance(a,b):判断对象a是否是b类或者b类的派生类实例化的对象
class A: passclass B(A): passclass C: passobj = B()print(isinstance(obj,B))print(isinstance(obj,A))print(isinstance(obj,C))"""结果:TrueTrueFalse"""
issubclass:类与类的关系 True/False
issubclass(a,b):判断a类是否是b类的子孙类
class A: passclass B(A): passclass C: passprint(issubclass(B,A))print(issubclass(C,A))"""结果:TrueFalse"""12.元类type
type:获取对象从属于的类
python中一切皆对象,类在某种意义上也是一个对象,python中自己定义的类以及大部分内置类,都是有type元类(构建类)实例化来的
type与object的关系:
print(type(object))#object类是type类的一个实例print(issubclass(type,object))#type类是object类的子孙类13.反射
? 程序对自己内部代码的一种自省方式
反射是什么:通过字符串去 *** 作对象的方式
反射是一个组合:hasattr、getattr、setattr、delattr(四个内置函数)
1.实例化对象的角度:class Human: country = '中国' def __init__(self,age): self.name = name self.age = age def func(self): print('is func')obj = Human('涛涛',80)#hasattr、getattr#hasattr返回True/False,getattr获取对象,没有会报错,可设置默认返回值print(hasattr(obj,'name'))f = getattr(obj,'func')f()#setattr,delattr用的少#setattr:添加属性,delattr删除属性setattr(obj,'sex','男')print(obj.__dict__)delattr(obj,'name')print(obj.__dict__)2.从类的角度:
class Human: country = '中国' def __init__(self,age): self.name = name self.age = age def func(self): print('is func') if hasattr(A,'country'): print(getattr(A,'country'))3.从其他模块:
import other#找到other.py对象的A类,实例化对象print(getattr(other,'A'))obj = getattr(other,'A')('涛涛')#对实例化对象反射取值print(getattr(obj,'name'))4.从当前模块:
import sysprint(sys.modules[__name__])#获取当前文件对象名def func1(): print('in 本模块这个对象') passgetattr(sys.modules[__name__],'func1')()#当本文件有很多函数(名字递增),反射调用所有函数:func_List = [f'func{i}' for i in range(1,5)]for func in func_List: getattr(sys.modules[__name__],func)()14.函数与方法的区别
? 1.总结:函数都是显性传参,方法都有隐形传参
python 中一切皆对象,类在某种意义上也是一个对象,python中自己定义的类,以及大部分内置类,都是由type元类(构建类)实例化得来的.
python 中一切皆对象,函数在某种意义上也是一个对象,函数这个对象是从FunctionType这个类实例化出来的.
python 中一切皆对象,方法在某种意义上也是一个对象,方法这个对象是从MethodType这个类实例化出来的.
1.通过打印函数名的方式区分什么是方法,什么是函数def func1(): passclass A: def func2(): pass passprint(func1)print(A.func2)"""通过类名调用的类中的方法叫做函数,结果:<function func1 at 0x0000022B99002F28><function A.func2 at 0x0000022B9AcdaBF8>"""obj = A()print(obj.func2)"""通过对象调用的方法叫方法,结果:<bound method A.func2 of <__main__.A object at 0x0000022B9ACD9198>>"""2.借助模块判断是方法还是函数
from types import FunctionTypefrom types import MethodTypedef func(): passclass A: def func(self): passobj = A()#FunctionType:判断是否为函数#MethodType:判断是否为方法print(isinstance(func,FunctionType)) # Trueprint(isinstance(A.func,FunctionType)) # Trueprint(isinstance(obj.func,FunctionType)) # Falseprint(isinstance(obj.func,MethodType)) # True15.特殊双下方法
? 双下方法:原来是开发python的程序员在源码中使用的。
双下方法:你不知道你干了什么就触发了双下方法
双下方法要慎用。
1.__len__():? 必须有返回值且返回值必须为int型
#计算实例化对象的属性个数class B: def __init__(self,age): self.name = name self.age = age def __len__(self):#返回对象的属性个数 return len(self.__dict__) passb = B('taotao',23)print(b.len(b))2.__hash__():
? 获取哈希值,必须有返回值且返回值必须是可哈希类型
class A: def __init__(self): self.a = 1 self.b = 2 def __hash__(self): return hash(str(self.a)+str(self.b)) passa =A()print(hash(a))3.__str__()、__repr__():
? 打印对象时触发,二者同时存在时,只执行__str__()。(str对象或repr对象也会触发)-->必须有返回值且返回值必须为字符串
class A: def __init__(self): pass def __str__(self): return '哈哈' def __str__(self): return '嘿嘿' passa = A()print(a)print(str(a))print('%s'%a)print(repr(a))4.__call__():****
? 当对象后面加括号或类()()触发执行从属于类(父类)的__call__方法。
class Foo: def __init__(self): pass def __call__(self,*args,**kwargs): print('__call__')obj = Foo()obj()5.__eq__():
? 判断是否相等
class A: def __init__(self): self.a = 1 self.b = 2 def __eq__(self,obj): if self.a == obj.a and self.b == obj.b: return Truea = A()b = A()print(a == b)@H_941_419@6.__del__():
? 析构方法,当对象在内存中被释放时,自动触发执行。
注:此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的。
class A: def __del__(self): print(666)obj = A()del obj7.__new__():***
? new一个对象,构造方法
类名()
先触发 object的__new__方法,此方法在内存中开辟一个对象空间. 执行__init__方法,给对象封装属性.1.__new__方法:
class A: def __init__(self): self.x = 1 print('in init function') def __new__(cls,**kwargs): print('in new function') return object.__new__(A)#object类中的方法 pass#对象时object类中的__new__方法产生了一个对象。a = A()#先执行__new__,在执行__init__,__init__中不能有return
2.python中的设计模式: 单例模式
? 一个类只允许实例化一个对象
优点:节省内存
#单例模型class A: __instance = None def __init__(self,name): self.name = name def __new__(cls,**kwargs): if not cls.__instance: cls.__instance = obj.__new__(cls) return cls.__instance passobj = A('alex')print(obj)obj1 = A('taotao')print(obj1)8.__item__():系列
? __getitem__ ()、__setitem__()、__delitem__():对象做类似于字典的(增删改查)触发item系列
__delattr__():对象. 属性 触发此方法
class Foo: def __init__(self,name): self.name = name def __getitem__(self,item):#查 print(item) return self.__dict__[item] def __setitem__(self,key,value):#增、改 self.__dict__[key] = value print(self.__dict__) def __delitem__(self,key):#删 super().__delattr__(key) print(self.__dict__) #删对象.属性触发 def __delattr__(self,item): super().__delattr__(item) print(self.__dict__) print(item)f1 = Foo('sb')print(f1['name'])f1['ac'] = 2del f1['ac']print(f1.__dict__)# del f1.ac# print(f1.name)9.__enter__()、__exit__ () with,上下文管理
实例化对象的第二种方式:必须基于enter和exit这两个方法
class A: def __init__(self,name): self.name = name def __enter__(self):#开启上下文管理器对象时触发此方法 self.name = self.name + '侬好' #第一步 print(111) return self #!!!必须写,将实例化的对象(self)返回 def __exit__(self,exc_type,exc_val,exc_tb):# 执行完上下文管理器对象f1时触发此方法 print(333)#第三步 self.name = self.name + '好个鸡儿'with A('sb') as obj: print(222) print(obj.name)#第二步print(obj.name)#第四步"""结果:111222sb侬好333sb侬好好个鸡儿"""10.__iter__():将对象变成可迭代对象
class A: def __init__(self,name): self.name = name def __iter__(self): for i in range(10): yIEld i def __next__(self): passobj = A('sb')# print('__iter__'in dir(obj))for i in obj: print(i)print(obj.name)o = iter(obj.name)print(next(o))16.异常处理:
异常处理的好处:
用户的体验良好 使代码更健壮性,容错性1.错误分类:语法错误,逻辑错误
如果你对错误信息不关心,只是想要排除错误让程序继续运行. 用万能异常
#万能异常:处理所有python识别的异常try: passexcept Exception as e: print(e) pass#单,多分支异常结构:你对错误信息要进行明确的分流,让你的程序多元化开发.try else finally
? except 必须依赖try,else必须依赖except和try,finally只依赖try
finally:在异常出现之前,执行finally中的语句
try: passexcept: passelse: print('如果没有异常则执行这里')finally: print(666)finally用处:用在关闭数据库连接,文件句柄关闭,数据保存等。
with open('test1.txt','r+',enCoding = 'utf-8') as f: try: for i in f1: print(i) finally: f1.close()#防止出现异常,文件不能关闭。在return结束函数之前,执行finally代码,在break之前执行:
def func(): try: print(111) return 333 finally: print(222) pass passprint(func())"""结果:111222333"""#在break之前执行while 1: try: print(111) break finally: print(222)主动触发异常:
raise ValueErro('出现了value错误')断言:展现一种强硬的态度
#assert 条件name = 'sb'n1 = input('name:')assert name == n1print(111)#如果name 不等于 n1,会直接报错自定义异常
python中提供了很多错误类型,但不是全部的错误
class SbError(BaseException):#自定义的错误必须继承于BaseException def __init__(self,msg): self.msg = msg def __str__(self): return self.msgtry: raise SbError('你犯错了')except SbError as e: print(e) """结果:你犯错了"""总结
以上是内存溢出为你收集整理的Python第六章 面向对象全部内容,希望文章能够帮你解决Python第六章 面向对象所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)