定义完类后直接就有的成员
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'>)
1、对象方法:
2、类方法
在类中定义的方法,使用类装饰器@classmethod进行了装饰
方法中有cls这个形参
不需要实例化对象,直接使用类进行调用
会把调用这个方法的类传递进来
3、绑定类方法
4、静态方法(和java的静态方法还是有很多不同的)
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
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)#很多,不贴了
1、__init__初始化方法
当时实例化对象之后就会立即出发的方法,完成对象的初始化操作
有个self参数,接受当前对象,其他参数根据需求定义集合
无返回值
2、__del__析构方法
当该类对象被销毁时,自动触发,用来关闭或释放对象创建时所使用的资源
有个self参数,接受当前对象
无返回值
3__new__构造方法
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__
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()#你把对象当成了函数调用
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
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
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
都可以转换其他类型的值为字符串
repr解析出来的值带引号
str函数会把对象转为更适合人类阅读的形式
repr函数会把对象转为解释器读取的形式
1、getattribute
2、getattr
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
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
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__魔术方法
# 定义一个描述符类 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
使用传统方法,初始化方法中实现
#要求学员分数只能在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()
使用描述符代理分数属性
# 要求学员分数只能在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
数据描述符:(完整)
同时具备三个魔术方法的类就是数据描述符
非数据描述符(不完整)
没有同时具备三个魔术方法
三种定义方式
class ScoreManage(): def __get__(self, instance, owner): pass def __set__(self, instance, value): pass def __delete__(self, instance): pass class Student(): score=ScoreManage()
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
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
为了完成某个功能或需求,根据经验和总结,对实现的代码步骤和代码设计进行的总结和归纳,形成的经典模式
设计模式在python中并不重要
同一个类只能创建一个对象去使用。
如何设计单例呢?
构造方法__new__
构造方法中加判断条件
创建一个属性,进行存储,默认值为None
如果没有对象,则创建对象,并且把对象存储起来
如果存储的事对象,则直接返回对象,就不需要创建新的对象了
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)#返回的是同一个实例
Mixin表示混入(mix-in)
使用Mixin混入类的好处
#交通工具类 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
# 导入抽象模块 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