Python(IT峰)笔记11-面向对象高阶,内置成员,方法的分类,面向对象的常用函数,魔术方法,str和repr的区别,成员相关魔术方法,描述符,描述符三种定义方式,单例模式,MixIn模式,抽象类
2021/9/20 17:27:32
本文主要是介绍Python(IT峰)笔记11-面向对象高阶,内置成员,方法的分类,面向对象的常用函数,魔术方法,str和repr的区别,成员相关魔术方法,描述符,描述符三种定义方式,单例模式,MixIn模式,抽象类,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
1、内置成员
定义完类后直接就有的成员
class Father(): pass class Demo(Father): ''' 类的说明文档 ''' name='zhangsan' age=20 def say(self): print('say somthing') res=Demo.__dict__ print(res)#{'__module__': '__main__', 'name': 'zhangsan', 'age': 20, 'say': <function Demo.say at 0x000001F03BC83700>, '__dict__': <attribute '__dict__' of 'Demo' objects>, '__weakref__': <attribute '__weakref__' of 'Demo' objects>, '__doc__': None} obj=Demo() obj.university='tingshua' print(obj.__dict__)#{'university': 'tingshua'} res=Demo.__doc__ print(res)#类的说明文档 res=obj.__doc__ print(res)#类的说明文档 #获取类名称 res=Demo.__name__ print(res)#Demo #获取当前文件夹 res=Demo.__module__ print(res)#__main__ #获取当前类的父类列表 res=Demo.__bases__ print(res)#(<class '__main__.Father'>,) #获取MRO列表,当前类的继承列 res=Demo.__mro__ print(res)#(<class '__main__.Demo'>, <class '__main__.Father'>, <class 'object'>)
2、方法的分类
1、对象方法:
- 在类中定义的方法,含有self参数
- 含有self的方法,只能通过对象调用
- 该方法把调用的对象传递进来
2、类方法
在类中定义的方法,使用类装饰器@classmethod进行了装饰
方法中有cls这个形参
不需要实例化对象,直接使用类进行调用
会把调用这个方法的类传递进来
3、绑定类方法
- 在类中定义的方法,不传递任何对象
- 只能使用类名来调用,不能使用对象来调用
- 不会传递对象或者类进来
4、静态方法(和java的静态方法还是有很多不同的)
- 在类中定义的方法没有参数
- 使用了装饰器符号@staticmethod进行了装饰
- 可以使用对象或类进行调用
- 不会传递任何参数进来
class Demo(): #对象方法:需要使用实例来调用,并传入self def func1(self): print('this is func1') #类方法,@classmethod装饰器关键字 @classmethod def func2(cls): print(cls) print('this is class funtion func2') #绑定类方法 def func3(): print('this is bind class function func3') #静态方法 @staticmethod def func4(): print('this is staticmethod func4') obj=Demo() obj.func1()#调用对象方法this is func1 Demo.func1('hello')#使用类名调用对象方法必须传入参数 #Demo.func1()#使用类名调用对象方法不传参会报错 Demo.func2()#使用类名去调用<class '__main__.Demo'>,this is class funtion func2 obj.func2()#即便使用了对象去调用,方法里面传递的依然是类,而不是对象 #绑定类方法直接使用类调用 Demo.func3()#this is bind class function func3 #obj.func3()#不能用对象来调用,用对象来调用会报错 #静态方法可以使用类和对象进行调用 Demo.func4()#this is staticmethod func4 obj.func4()#this is staticmethod func4
3、面向对象的常用函数
- issubclass()子类检测
- isinstance()实例检测
- hasattr()检测类/对象是否包含指定名称的成员
- getattr()获取类/对象的成员的值
- setattr()设置类/对象的成员的值
- delattr()删除类/对象的成员,和del直接删除对象的成员是一样的结果
- dir()获取对象所有可以访问的成员的列表
class A(): pass class B(A): pass class C(A): pass class D(B,C): name='zhagnsan' age=34 def say(self): print('i want to say somthing') #issubclass()子类检测 res=issubclass(D,B) print(res)#True #isinstance()实例检测 d=D() res=isinstance(d,D) print(res)#True #hasattr()检测类/对象是否包含指定名称的成员 res=hasattr(D,'name') print(res)#True res=hasattr(d,'name') print(res)#True #getattr()获取类/对象的成员的值 res=getattr(d,'name') print(res)#zhagnsan #setattr()设置类/对象的成员的值 setattr(d,'name','lisi') res=getattr(d,'name') print(res)#lisi print('---') #delattr()删除类/对象的成员,和del直接删除对象的成员是一样的结果 delattr(d,'name') print(d.name)#zhangsan,这里lisi被删除,但去保留了类里面的name, print(D.name)#zhangsan print('===') delattr(D,'name') #print(d.name)#都会报错,因为类的属性都没有了,对象的属性也不再了 #print(D.name)#都会报错 #dir()获取对象所有可以访问的成员的列表 res=dir(d) print(res)#很多,不贴了
4、魔术方法(上)
1、__init__初始化方法
当时实例化对象之后就会立即出发的方法,完成对象的初始化操作
有个self参数,接受当前对象,其他参数根据需求定义集合
无返回值
2、__del__析构方法
当该类对象被销毁时,自动触发,用来关闭或释放对象创建时所使用的资源
有个self参数,接受当前对象
无返回值
3__new__构造方法
- 实例化对象时自动触发,在__init__之前触发
- 管理控制对象创建的过程
- 一个cls参数,接受当前类,其他参数根据初始化方法的参数进行决定
- 返回值可有可无,如果返回,必须返回object.new(cls)进行对象的创建,如果没有返回值,则实例化对象的结果为None
- __new__方法的参数和__init__方法的参数要保持一致,除了第一个参数。
- 设计模式中的单例模式往往需要用到
class Person(): # 构造方法 def __new__(cls, *args, **kwargs): print('触发了构造方法') print(args) # ('zhangsan', 34, 'female') print(kwargs) # {} # 如果没有在该方法(构造方法)中返回对象,则对象无法创建 return object.__new__(cls) # cls是当前类,将构造好的对象返回出去 def __init__(self, name, age, gender): print('触发了初始化方法') self.name = name self.age = age self.gender = gender def __del__(self): print('触发了析构方法') p1 = Person('zhangsan', 34, 'female') print(p1.name) print(p1)
运行结果
触发了构造方法 ('zhangsan', 34, 'female') {} 触发了初始化方法 zhangsan <__main__.Person object at 0x00000216EE079400> 触发了析构方法
4__call__
- 把对象当作函数直接调用时自动触发
- 一般用于归纳类或对象的操作步骤,方便调用
- 一个self参数接收当前对象,其他参数根据调用需求决定
- 返回值可有可无
class Person(): # 构造方法 def __new__(cls, *args, **kwargs): print('触发了构造方法') print(args) # ('zhangsan', 34, 'female') print(kwargs) # {} # 如果没有在该方法(构造方法)中返回对象,则对象无法创建 return object.__new__(cls) # cls是当前类,将构造好的对象返回出去 def __init__(self, name, age, gender): print('触发了初始化方法') self.name = name self.age = age self.gender = gender def __del__(self): print('触发了析构方法') def __call__(self, *args, **kwargs): print('你把对象当成了函数调用') p1 = Person('zhangsan', 34, 'female') print(p1.name) print(p1) p1()#你把对象当成了函数调用
5、魔术方法(下)
1、len
当使用len函数去检测当前对象的时候自动触发
可以使用len函数检测当前对象中某个数据的信息
一个self参数,接受当前对象
必须要有返回值,并且必须是一个整型
len要获取什么属性的值,就在返回值中返回那个属性的长度集合
class Demo(): listur=[1,3,5,6] #可以替代对象使用len函数,并返回一个指定的整型数 def __len__(self): return len(self.listur) obj=Demo() res=len(obj) print(res)#4
2、str
- 当使用str或print函数对对象进行操作时触发
- 对对象进行字符串的返回,可以自定义返回的字符串
- 需要一个self参数,接收当前对象
- 返回值必须要有,并且是字符串类型的值
class Demo(): listur=[1,3,5,6] #可以替代对象使用str函数,并返回一个自定义的字符串 def __str__(self): return '本脚本,Demo object字符转换' obj=Demo() res=str(obj)#本脚本,Demo object字符转换,转换字符串操作。使用的是继承自object类的str函数 print(res) print(obj)#本脚本,Demo object字符转换,转换字符串操作,实际是自定义了一个属于自己的str函数
3、repr
- 上例中,如果没有使用__str__方法,也可以使用__repr__方法替换
- 在使用repr方法对当前对象进行转换时自动触发
- 可以设置repr函数操作对象的结果
- 需要一个self参数,接收当前对象
- 返回值必须要有,并且是字符串类型的值
- 正常情况下__str__方法和__repr__方法是可以互相替代的
class Demo(): listur=[1,3,5,6] #可以替代对象使用str函数,并返回一个自定义的字符串 # def __str__(self): # return '本脚本,Demo object字符转换' def __repr__(self): return '本脚本,Demo object字符转换' obj=Demo() res=str(obj)#本脚本,Demo object字符转换,转换字符串操作。使用的是继承自object类的str函数 print(res) print(obj)#本脚本,Demo object字符转换,转换字符串操作,实际是自定义了一个属于自己的str函数
4、bool
当使用bool函数转换当前对象时,会自动触发,默认情况下,对象会转为True
可以代替对象进行bool类型的转换,可以转换任意数据
self参数接收对象
必须返回一个bool类型的返回值
class Demo(): listur=[] def __bool__(self): return bool(self.listur) obj=Demo() res=bool(obj) print(res)#False,如果没有魔术方法,返回True
6、str和repr的区别
都可以转换其他类型的值为字符串
repr解析出来的值带引号
str函数会把对象转为更适合人类阅读的形式
repr函数会把对象转为解释器读取的形式
7、成员相关魔术方法
1、getattribute
- 当访问对象成员时自动触发,无论当前成员是否存在
- 可以在获取对象成员时,对数据进行一些处理
- 需要一个self参数,接收对象,一个item接收当前访问的成员名称
- 返回值可有可无,返回值就是访问的结果
- 在当前魔法方法中,禁止对当前对象的成员访问,因为会触发递归。
- 如果要在当前魔术方法中访问对象成员必须使用object.getattribute(self,item)进行访问
2、getattr
- 当访问对象不存在的成员时,自动触发
- 防止访问不存在的成员时报错,也可以为不存在的成员进行赋值操作
- 需要一个self参数接收当前对象,一个item接受当前访问的成员名称
- 当存在__getattribute__的方法时,会去执行这个__getattribute__方法因为这个方法优先级gao
class Person(): name='name' age=34 gender='male' def __init__(self,name,age,gender): self.name=name self.age=age self.gender=gender def say(self): print('talk somthing') def sing(self): print('sing a song') # def __getattribute__(self, item): # #在方法中使用object来获取属性值 # res=object.__getattribute__(self,item)#获取类成员必须要使用这种格式 # return res def __getattr__(self, item): return False p1=Person('lisi',11,'female') print(p1.name)#lisi,访问存在的成员 print(p1.home)#False。访问不存在的成员反馈回来的内容
3、setattr
- 当给对象的成员进行赋值操作的时候会自动触发,包括添加,修改
- 可以限制或管理对象成员的添加和修改操作
- 接受三个参数1,一个self参数,接受当前对象,2,设置的成员名,3成员属性的值
- 无返回值
- 在当前的魔术方法中禁止给当前对象的成员直接进行赋值操作,会触发递归
- 如果需要赋值操作,需要借助object。使用object.__setattr(self,item,value)
class Person(): name='name' age=34 gender='male' def __init__(self,name,age,gender): self.name=name self.age=age self.gender=gender def say(self): print('talk somthing') def sing(self): print('sing a song') # def __getattribute__(self, item): # #在方法中使用object来获取属性值 # res=object.__getattribute__(self,item)#获取类成员必须要使用这种格式 # return res def __getattr__(self, item): return False def __setattr__(self, key, value): print(self,key,value) p1=Person('lisi',11,'female') print(p1.name)#lisi,访问存在的成员 print(p1.home)#False。访问不存在的成员反馈回来的内容 p1.world='hello'#<__main__.Person object at 0x000001987654B460> world hello
4、delattr
- 当删除对象成员时自动触发
- 可以限制对象成员的删除,还可以删除不存在成员时防止报错
- 参数有伞,1、self接收当前对象,2,、item删除的成员名称
- 无返回值
- 在当前魔术方法中禁止直接删除对象的成员,会触发递归操作
- 如果想要删除当前对象的成员需要借助object。格式为object.delattr(self,item)
class Person(): name='name' age=34 gender='male' def __init__(self,name,age,gender): self.name=name self.age=age self.gender=gender def say(self): print('talk somthing') def sing(self): print('sing a song') def __del__(self,item): print(item) object.__delattr__(self,item) p1=Person('lisi',11,'female') del p1.name print(p1.name)#报错
访问成员的顺序
1、调用__getattribute__
2、调用数据描述符
3、调用当前对象的成员
4、调用当前类的的成员
5、调用非数据描述符
6、调用父类的成员
7、调用__getattr__魔术方法
8、描述符类似于java的getter,setter
- 其实就是一个类
- 当一个类,包含了仨个魔术方法(get , set,delete,)或之一的,那么这个类就称之为描述符类
- 描述符的作用就是对一个类中的某个成员进行一个详细的管理操作(获取,修改,删除)
- 描述符就是代理了一个类中的成员的操作,描述符属于类,只能定义为类的属性
- 一个类成员的值,是另一个描述符类的对象,那么当对这个类中的成员进行操作时,可以理解为是对另一个对象的操作(关联过去的)
# 定义一个描述符类 class PersonName(): __name = 'zhangsan' def __get__(self, instance, owner): print(self) print(instance) print(owner) return self.__name def __set__(self, instance, value): self.__name=value def __delete__(self, instance): #del self.__name print('不允许删除') class Person(): name = PersonName() p1 = Person() print(p1.name)#实际打印的是PersonName(先Person,后关联到PersonName) #打印出<__main__.PersonName object at 0x00000287F882B460> #打印出<__main__.Person object at 0x00000287F8839400> #打印出<class '__main__.Person'> #打印出zhangsan p1.name='lisi' print(p1.name)#lisi
9、描述符案例
使用传统方法,初始化方法中实现
#要求学员分数只能在1-100范围内 #方法1,在init函数中做判断 class Student(): def __init__(self,id,name,score): self.id = id self.name = name #self.score = score if score<100 and score>0: self.score = score else: print('分数不符合要求') def returnMe(self): info= f''' 学员编号:{self.id} 学员姓名:{self.name} 学员分数:{self.score} ''' print(info) s1=Student('001','zhagnsan',99) s1.returnMe()#打印出学员信息
使用setattr魔术方法
# 要求学员分数只能在1-100范围内 # 方法1,在init函数中做判断 class Student(): def __init__(self, id, name, score): self.id = id self.name = name self.score = score def __setattr__(self, key, value): if key == 'score': if value < 100 and value > 0: object.__setattr__(self, key, value) else: print('当前分数不符合要求') else: object.__setattr__(self, key, value) def returnMe(self): info = f''' 学员编号:{self.id} 学员姓名:{self.name} 学员分数:{self.score} ''' print(info) s1 = Student('001', 'zhagnsan', 99) s1.returnMe() # 打印出学员信息 s1.score=-34#当前分数不符合要求 s1.returnMe()
使用描述符代理分数属性
- 定义Score描述符类
- 把学生类中的score这个成员交给描述符类进行代理
- 只要在代理的描述符类对分数进行赋值和获取
# 要求学员分数只能在1-100范围内 # 定义Score类代理分数操作 class Score(): __score = None def __get__(self, instance, owner): return self.__score def __set__(self, instance, value): if value > 0 and value < 100: self.__score = value else: print('分数输入错误') def __delete__(self, instance, owner): pass class Student(): score=Score() def __init__(self, id, name, score): self.id = id self.name = name self.score = score def returnMe(self): info = f''' 学员编号:{self.id} 学员姓名:{self.name} 学员分数:{self.score} ''' print(info) s1 = Student('001', 'zhagnsan', 99) s1.returnMe() # 打印出学员信息 s1.score=-33#分数输入错误 s1.score=34 s1.returnMe()#34
10、描述符三种定义方式
数据描述符:(完整)
同时具备三个魔术方法的类就是数据描述符
非数据描述符(不完整)
没有同时具备三个魔术方法
三种定义方式
- 1、通过定义描述符类来实现
class ScoreManage(): def __get__(self, instance, owner): pass def __set__(self, instance, value): pass def __delete__(self, instance): pass class Student(): score=ScoreManage()
- 2、使用property函数来实现
在当前需要被管理的类中,直接定义类似下面的三个方法
class Student(): #在函数中以参数的形式指定对应的方法 def getScore(self): print('getScore') def setScore(self,value): print('setScore',value) def delScore (self): print('delScore') #在property函数中指定对应的三个方法,第一个方法对应__get__,第2个方法对应__set__,第3个方法对应__delete__ score=property(getScore,setScore,delScore) s1=Student() print(s1.score)#getScore,None s1.score=200#setScore 200 del s1.score#delScore
- 3、使用装饰器语法@property来实现
class Student(): __score = None @property def score(self): print('get') return self.__score @score.setter def score(self, value): print('set') self.__score = value @score.deleter def score(self): print('delete') del self.__score s1=Student() print(s1.score) s1.score=33 print(s1.score) del s1.score
11、设计模式–单例模式
为了完成某个功能或需求,根据经验和总结,对实现的代码步骤和代码设计进行的总结和归纳,形成的经典模式
设计模式在python中并不重要
同一个类只能创建一个对象去使用。
如何设计单例呢?
- 1、需要有一个方法可以控制当前对象的创建
构造方法__new__
- 2、在这个方法中,需要存储一个标识,去检测是否有对象
构造方法中加判断条件
创建一个属性,进行存储,默认值为None
- 3、在创建对象的方法中,去检测和判断是否有对象
如果没有对象,则创建对象,并且把对象存储起来
如果存储的事对象,则直接返回对象,就不需要创建新的对象了
class Demo(): # 1、定义私有属性存储对象,默认为None __obj = None # 2、定义构造方法 def __new__(cls, *args, **kwargs): pass # 3、在创建对象的过程中,判断是否有对象 if cls.__obj: # 说明有对象 return cls.__obj else: # 如果没有对象,则创建对象 obj = object.__new__(cls) # 并存储起来 cls.__obj = obj # 在返回对象 return cls.__obj a=Demo()#<__main__.Demo object at 0x000002A273FC9400> b=Demo()#<__main__.Demo object at 0x000002A273FC9400> print(a,b)#返回的是同一个实例
12、设计模式–Mixin模式(混合设计模式)
- python支持多继承
- 继承需要有一个必要的前提,继承应该是一个‘is-a’的关系
- is-a就是说某个实例是另一个类的所属,is-a就是要拒绝多继承
- 解决方案就是,给其中一个需要继承的类,定义为一个mixin混合类
Mixin表示混入(mix-in)
- Mixin必须是表示一种功能,而不是一个对象
- Mixin的功能必须单一,如果有多个功能,那就多定义Mixin类
- python的Mixin是通过多继承实现的
- Mixin这个类通常不单独使用,而是混合到其他类中,去增加功能
- Mixin类不依赖子类的实现,即便子类没有继承这个Mixin,子类也能正常地运行,可能就是缺少了一些功能而已。
使用Mixin混入类的好处
- 1、Mixin这个混入类的设计模式,在不对类的内容修改的前提下,扩展了类的功能
- 2、Mixin呼入类为了提高代码的重用性,使代码的结构更加的简单清晰
- 3、可以根据开发需求任意调整功能(创建新的Mixin混入类)
- 4、避免设计多层次的复杂的继承关系
#交通工具类 class vehicle(): #运货 def carry(self): print('运输货物') #载客 def take(self): print('搭载乘客') #飞行器类 ,定义为Mixin混合类(这里仅仅是名称上做了个区别) ,此时等于把飞行器这个类,作为了一个扩展的功能,来实现多个类 class aircraftMixin(): def fly(self): print('可以起飞了') #汽车类 class Car(vehicle): pass #定义飞机类 class airplane(vehicle,aircraftMixin): pass #直升机类 class helicopter(vehicle,aircraftMixin): pass
13、设计模式–抽象类
- 抽象类是一个特殊的类(和java的抽象类概念相似)
- 不能直接使用,不能直接实例化为一个对象
- 抽象类中包含了抽象方法,抽象方法没有实现代码
- 抽象类需要子类继承,并重写父类的方法才可以使用
- 需要导入abc模块import abc。并且类的metaclass属性必须是abc.ABCMeta
- 抽象方法必须使用抽象装饰符@abc.abstractclassmethod进行装饰
# 导入抽象模块 import abc #定义抽象类 class WriteCode(metaclass=abc.ABCMeta): # 类的metaclass属性必须是abc.ABCMeta # 定义需要的抽象方法,要使用装饰器进行装饰 @abc.abstractclassmethod def write_php(self): pass def write_java(self): print('直接实现,子类不重写') def write_python(self): print('也可以不抽象直接实现') #定义子类,继承抽象类,并实行抽象类的抽象方法 class RealWrite(WriteCode): def write_php(self): print('write php code') def write_python(self): print('write python code') w1=RealWrite()#报错,抽象类不能实例化对象 w1.write_java()#直接实现,子类不重写 w1.write_php()#write php code w1.write_python()#write python code
这篇关于Python(IT峰)笔记11-面向对象高阶,内置成员,方法的分类,面向对象的常用函数,魔术方法,str和repr的区别,成员相关魔术方法,描述符,描述符三种定义方式,单例模式,MixIn模式,抽象类的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-21Python编程基础教程
- 2024-11-20Python编程基础与实践
- 2024-11-20Python编程基础与高级应用
- 2024-11-19Python 基础编程教程
- 2024-11-19Python基础入门教程
- 2024-11-17在FastAPI项目中添加一个生产级别的数据库——本地环境搭建指南
- 2024-11-16`PyMuPDF4LLM`:提取PDF数据的神器
- 2024-11-16四种数据科学Web界面框架快速对比:Rio、Reflex、Streamlit和Plotly Dash
- 2024-11-14获取参数学习:Python编程入门教程
- 2024-11-14Python编程基础入门