# 内置成员 def func(): pass class Demo(): ‘‘‘ 此处是类的说明文档 ‘‘‘ name = ‘a‘ age = 20 def say(self): print(‘会说会唱会rap...‘) obj = Demo() obj.san = ‘aaa‘ obj.f = func # 获取类/对象的所属成员 res = Demo.__dict__ print(res) res = obj.__dict__ print(res) # 获取类的文档信息 对象/类.__doc__ res = Demo.__doc__ print(res) res = obj.__doc__ print(res) # 获取类名称组成的字符串 res = Demo.__name__ print(res) # 获取类所在文件的名称,如果是当前文件则为__main__ res = Demo.__module__ print(res) # bases 获取当前类的父类列表(只获取上一级父级) __base__只获取第一个继承的父类 res = Demo.__bases__ print(res) # mro 获取当前类的继承链 res = Demo.__mro__ print(res) # 获取对象的所有属性和方法(包括继承来的) res = obj.__dir__() print(res)
‘‘‘ 1.对象方法 特征: 1.在类中定义的方法,含有self参数 2.含有self的方法,只能使用对象进行调用 3.该方法会把调用的对象传递进来 2.类方法 特征: 1.在类中定义的方法,使用装饰器 @classmethod 进行了装饰 2.方法中有cls这个形参 3.不需要实例化对象,直接使用类进行调用 4.会把调用这个方法的类传递进来 5.即便用对象去调用该方法,传递进来的还是对象所属的类 3.绑定类方法 特征: 1.在类中定义的方法,没有任何参数 2.只能使用类进行调用 3.不会传递对象和类进来,但可以传一般的参数 4.静态方法 特征: 1.在类中定义的方法,没有任何参数 2.在类中定义的方法,使用装饰器 @staticmethod 进行了装饰 3.可以使用对象或类去调用 4.不会传递对象和类进来,但可以传一般的参数 ‘‘‘ class Demo(): # 对象方法 def func1(self): print(self) print(‘this is object function func1‘) # 类方法 @classmethod def func2(cls): print(cls) print(‘this is class function func2‘) # 绑定类方法 def func3(): print(‘this is bind function func3‘) # 静态方法 @staticmethod def func4(): print(‘this is static function func4‘) # 实例化对象 obj = Demo() # 对象方法 # obj.func1() # 类方法 # Demo.func2() # obj.func2() # 绑定类方法 # 不能使用对象去调用 Demo.func3() # 静态方法 Demo.func4() obj.func4()
class A(): pass class B(A): pass class C(A): pass class D(B,C): name = ‘a‘ age = 20 def say(self): pass # issubclass(子类,父类) 检测一个类是不是另一个类的子类 # isinstance() 检测一个对象是不是指定类或者该类的子类的实例化对象 obj = D() # res = isinstance(obj,A) # print(res) # hasattr() 检测类/对象是否包含指定名称的成员(私有检测不到,但继承的可以) res = hasattr(D,‘name‘) print(res) res = hasattr(obj,‘name‘) print(res) # 获取类或对象的成员的值 res = getattr(obj,‘name‘) print(res) # setattr() 设置类/对象的成员的属性值 setattr(obj,‘name‘,‘ooo‘) print(obj.name) # delattr() 删除类/对象的成员属性 与del一样 delattr(obj,‘name‘) print(obj.name) # dir() 获取对象所有可以访问的成员 res = dir(obj) print(res) res = obj.__dir__() print(res)
‘‘‘ 1.__init__ 初始化方法 ***** 触发机制:通过类实例化对象自动触发的一个方法 作用: 可以在对象实例化后完成对象的初始化(属性赋值,方法的调用) 参数: 一个self,接受当前的对象,其他参数根据需求进行定义即可 返回值: 无 注意事项:无 2.__new__ 构造方法 **** 触发机制:实例化对象时自动触发(在__init__之前触发) 作用: 管理控制对象的创建过程 参数: 一个cls,接受当前类,其他参数根据初始化方法的参数进行决定 返回值: 必须返回object.__new__(cls)进行对象的创建,如果没有返回值,则实例化对象的结果为None 注意事项:__new__方法的参数和__init__方法的参数要保持一致,除了第一个参数 必须返回object.__new__(cls)进行对象的创建,如果没有返回值,则实例化对象的结果为None 应用场景:设计模式中的单例设计模式 3.__del__ 析构方法 ***** 触发机制:当前类实例化的对象被销毁时,自动触发 作用: 可以在析构方法中完成一些特殊任务,比如在初始化方法中打开的文件可以关闭 参数: 一个self,接受当前的对象 返回值: 无 注意事项:是对象被销毁时触发了这个方法,而不是这个方法销毁了对象 4.__call__ *** 触发机制:把对象当做函数直接调用时自动触发 作用: 一般用于归纳类或对象的操作步骤,方便调用 参数: 一个self,接受当前的对象,其余参数根据调用需求 返回值: 可有可无 注意事项: ‘‘‘ # 定义人类 class Person(): # 构造方法 def __new__(cls, *args, **kwargs): print(‘触发了构造方法...‘) print(args) print(kwargs) # 如果在该方法中没有返回对象,则创建对象失败 return object.__new__(cls) # 初始化方法 def __init__(self,name,age,sex,position): print(‘触发了初始化方法...‘) self.name = name self.age = age self.sex = sex def __call__(self, *args, **kwargs): print(‘你把对象当成了函数进行调用‘) # 析构方法 def __del__(self): print(‘触发了析构方法...‘) # 实例化对象 zs = Person(‘张三丰‘,180,‘男‘,position = ‘Python‘) zs()
‘‘‘ 1.__len__ 触发机制:当使用len函数去检测当前对象的时候自动触发 作用: 可以使用len函数检测当前对象中的某个数据信息 参数: 一个self,接受当前的对象 返回值: 必须有,并且必须是一个整形 注意事项:len要获取什么属性的值,就在返回值中返回哪个属性的长度即可 2.__str__ 触发机制:当使用str或者print函数去操作对象的时候自动触发 作用: 代替对象字符串的返回,可以自定义返回的信息 参数: 一个self,接受当前的对象 返回值: 必须有,并且必须是一个字符串 注意事项:无 3.__repr__ 触发机制:当使用repr方法对当前对象进行转换时自动触发 作用: 可以设置repr函数操作对象的结果 参数: 一个self,接受当前的对象 返回值: 必须有,并且必须是一个字符串 注意事项:正常情况下,如果没有__str__这个魔术方法,__repr__方法就会代替__str__ 4.__bool__ 初始化方法 触发机制:当使用bool函数去转换当前对象的时候自动触发,默认情况下,对象转换为True 作用: 可以代替对象进行bool类型的转换,可以转换任何数据 参数: 一个self,接受当前的对象 返回值: 必须是一个bool类型 注意事项:无 ‘‘‘ class Demo(): listurl = [] # 可以代替对象使用len函数,并返回一个指定的整型 def __len__(self): return len(self.listurl) # 可以代替对象进行str或者print的字符串信息返回 def __str__(self): return ‘<本脚本。Demo 对象> str‘ def __repr__(self): return ‘repr 被触发了‘ def __bool__(self): return bool(self.listurl) obj = Demo() print(len(obj)) print(obj) print(repr(obj)) res = bool(obj) print(res)
# 认识 str 和 repr 的区别 num = 521 r1 = str(num) r2 = repr(num) # str 和 repr 函数都可以把其它类型的值转换为字符串 print(r1,type(r1)) print(r2,type(r2)) num = ‘521‘ r1 = str(num) r2 = repr(num) print(r1,type(r1)) print(r2,type(r2)) ‘‘‘ str 和 repr 函数都可以把其它类型的值转换为字符串 str函数会把对象 转化为 更适合人类阅读的形式 repr函数会把对象 转化为 解释器读取的形式 如果数据对象并没有更明显的区别的话,str和repr的结果是一样的 ‘‘‘ class Demo(): def __str__(self): return ‘123‘ def __repr__(self): return ‘123‘ pass obj = Demo() r1 = str(obj) r2 = repr(obj) print(r1) print(r2)
‘‘‘ 1.__getattribute__(self, item) 触发机制:当访问对象成员时,自动触发,无论当前成员是否存在 作用: 可以在获取对象成员时,对数据进行一些处理 参数: 一个self接受当前的对象,一个item接受当前访问的成员 返回值: 可有可无,返回的值可以是访问的结果 注意事项:在当前的魔术方法中,禁止使用 对象.成员 的方式进行成员访问,会触发递归操作 如果想要在当前魔术方法中访问对象的成员必须使用object.__getattribute__来进行访问 格式:object.__getattribute__(self,item) 2.__getattr__ 触发机制:当访问对象中不存的成员时,自动触发 作用: 防止访问不存在的成员时报错,也可以为不存在的成员进行赋值操作 参数: 一个self接收当前对象,一个item接收当前访问的成员名称 返回值:可有可无 注意事项:当存在__getattribute__时,只会执行__getattribute__ 3.__setattr__ 触发机制:当给对象的成员进行赋值操作时会自动触发(包括添加,修改) 作用: 可以限制或管理对象成员的添加和修改操作 参数: 1.self 2.key 设置成员名 3.val 设置的成员值 返回值: 无 注意事项:在当前的魔术方法中禁止给当前的对象的成员直接进行赋值操作,会触发递归 如果想要给当前的对象成员进行赋值,需要借助object 格式:object.__setattr__(self,key,val) 4.__delattr__ 触发机制:当删除对象成员时自动触发 作用: 可以限制对象成员的删除,还可以删除不存在成员时防止报错 参数: 1.self 2.item 删除的成员名称 返回值: 无 注意事项:在当前的魔术方法中禁止直接删除对象的成员,会触发递归操作 如果想要删除当前对象成员,需要借助object 格式:object.__delattr__(self,item) ‘‘‘ class Person(): name = ‘名字‘ age = ‘年龄‘ sex = ‘性别‘ def __init__(self,n,a,s): self.name = n self.age = a self.sex = s def say(self): print(‘聊聊人生,谈谈理想...‘) def sing(self): print(‘高歌一曲...‘) # def __getattribute__(self, item): # # res = object.__getattribute__(self,item) # # 可以在获取对象成员时,对数据进行一些处理 # # print(item,type(item)) # # return res[0]+‘*‘+res[-1] # # if item == ‘say‘: # return object.__getattribute__(self,item) # else: # res = object.__getattribute__(self, item) # return res[0] + ‘*‘ + res[-1] def __getattr__(self, item): try: print(item+‘__getattr__‘) except: return False # 若没有给对象成员进行赋值,那么对象成员赋值失败 def __setattr__(self, key, value): object.__setattr__(self, key, value) # pass def __delattr__(self, item): object.__delattr__(self,item) # pass # 实例化对象 zs = Person(‘张三丰‘,180,‘男‘) print(zs.name) zs.abc zs.abc = ‘111‘ print(zs.abc) del zs.abc print(zs.abc) ‘‘‘ 访问成员的顺序: 1.调用__getattribute__魔术方法 2.调用数据描述符(后面会讲) 3.调用当前对象的成员 4.调用当前类的成员 5.调用非数据描述符 6.调用父类的成员 7.调用__getattr__魔术方法 ‘‘‘
‘‘‘ 描述符: 当一个类中,包含三个魔术方法(__get__,__set__,__delete__)之一,或者全部时,那么 这个类就称为描述符类 作用; 描述符的作用就是对一个类中的某个成员进行一个详细的管理操作(获取,赋值,删除) 描述符就是代理了一个类中的成员操作,描述符属于类,只能定义为类的属性 ‘‘‘ # 定义描述符类 class PersonName(): __name = ‘name‘ def __get__(self, instance, owner): print(self) print(instance) print(owner) print(‘get‘) return self.__name def __set__(self, instance, value): print(‘set‘) self.__name = value def __delete__(self, instance): print(‘delete‘) del self.__name class Person(): name = PersonName() zs = Person() print(zs.name) zs.name = ‘s‘ print(zs.name) del zs.name print(zs.name)
‘‘‘ # 要求学员的分数只能在0-100之间 解决方法: 1.在__init__方法中检测当前分数范围 # 检测分数范围 if score >= 0 and score <= 100: self.score = score else: print(‘当前分数不符合要求‘) 缺点:这个解决方案只能在对象初始化时有效。 2.定义一个setattr def __setattr__(self, key, value): # 检测是否是给score进行赋值操作 if key == ‘score‘: if value >= 0 and value <= 100: object.__setattr__(self, key, value) else: object.__setattr__(self, key, None) print(‘当前分数不符合要求‘) else: object.__setattr__(self,key,value) 缺点:假如 学员的分数不止一个时怎么办, 另外就是当前这个类中的代码是否就比较多了呢? 3.可以思考使用描述符来代理我们的分数这个属性 1.定义Score描述符类 2.把学生类中的score这个成员交给描述符类进行代理 3.只要在代理的描述符类中对分数进行赋值和获取就ok ‘‘‘ # 定义描述符类 代理分数的管理 class Score(): __score = 0 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 __del__(self): del self.__score # 定义一个学生类,需要记录学生的id,名字,分数 class Student(): score = Score() def __init__(self,id,name,score): self.id = id self.name = name self.score = score # # 检测分数范围 # if score >= 0 and score <= 100: # self.score = score # else: # print(‘当前分数不符合要求‘) def returnMe(self): info = f‘‘‘ 学员编号:{self.id} 学员姓名:{self.name} 学员分数:{self.score} ‘‘‘ print(info) # def __setattr__(self, key, value): # # 检测是否是给score进行赋值操作 # if key == ‘score‘: # if value >= 0 and value <= 100: # object.__setattr__(self, key, value) # else: # object.__setattr__(self, key, None) # print(‘当前分数不符合要求‘) # else: # object.__setattr__(self,key,value) # 实例化对象 zs = Student(1011,‘站三丰‘,100) zs.returnMe() # zs.score = -20
‘‘‘ 数据描述符类 同时具备三个魔术方法的类就是数据描述符类 非数据描述符类 只具备其中几个魔术方法的类就是非数据描述符类 ‘‘‘ ‘‘‘ # 格式一 通过定义 描述符类来实现 class ScoreManage(): score = 100 def __get__(self, instance, owner): print(self) print(instance) print(owner) return self.score def __set__(self, instance, value): pass def __delete__(self, instance): pass class Student1(): score = ScoreManage() s = Student1() print(s.score) ‘‘‘ ‘‘‘ # 格式二, 使用 property 函数来实现 class Student2(): __score = 100 # 在当前需要被管理的类中,直接定义类似下面三个方法 def getscore(self): print(self) print(‘getsocer‘) return self.__score def setscore(self,value): print(‘setsocer‘,value) def delscore(self): print(‘delsocer‘) # 在函数中指定对应的三个方法 # 参数对应:1.get 2.set 3.del score = property(getscore,setscore,delscore) zs = Student2() print(zs.score) zs.score = 100 del zs.score ‘‘‘ # 格式三,使用@property 装饰器语法来实现 class Student(): __score = None @property def score(self): print(self,‘get‘) return self.__score @score.setter def score(self,value): print(‘set‘) self.__score = value @score.deleter def score(self): print(‘del‘) del self.__score ls = Student() ls.score ls.score = 100 del ls.score ‘‘‘ 在后面的两种格式中,必须把要代理的属性(比如score)设置为其他属性(常设置为__score) 防止引发递归调用 ‘‘‘
‘‘‘ 单例设计模式: 在当前脚本中,同一个类只能实例化一个对象,去使用。 实现单例的案例,思考: 单例和婚姻法的关系,特别像,一个人只能有一个结婚对象 在社会中是如何完成一夫一妻制的? 如果要结婚,必须要到 民政局 登记 民政局 需要检测两个人的户口本,看上面是否属于 结婚的状态 如果是已婚,肯定就撵出去。 如果没有结婚,可以给盖个章,开始登记。 那么按照这样的思路如果去实现 python中的单例设计模式 1. 需要有一个方法,可以去控制当前对象的创建? 构造方法__new__ 2. 需要有一个标识来存储个表示是否有对象 创建一个属性 进行存储,默认值为None 3. 在创建对象的方法中去检测和判断是否由对象? 如果没有对象,则创建对象,并且把对象存储起来 如果存储的是对象,则直接返回对象,就不需要创建新的对象了 ‘‘‘ class Demo(): __obj = None def __new__(cls, *args, **kwargs): if not cls.__obj: cls.__obj = object.__new__(cls) return cls.__obj def func(self): print(‘xxxxx‘) a = Demo() b = Demo() print(a) print(b) a.func()
‘‘‘ 继承需要有一个必要的前提,继承应该是个‘is-a‘ 的关系 例如: 苹果可以去继承水果,因为苹果就是一个水果 苹果不能继承午饭,因为午饭可以有苹果也可以没有 比如汽车可以继承交通工具,因为汽车本身就是一个交通工具 交通工具有哪些? 汽车,飞机,直升机,这些都属于交通工具 那么如何去设计这些类的关系呢? 比如创建一个交通工具类,然后属于交通工具的都来继承,再去实现。 但是,飞机和直升机都有 飞行的功能,而汽车并没有,那么在交通工具中如果去定义飞行这个功能, 那就不太合适了。。 能不能在飞机和直升机类中分别实现飞行这个功能呢?可以,但是代码又无法重用。 怎么办? 单独去定义交通工具类,和飞行器 这个两个父类,这样飞机和直升机就可以去继承这两个类,但是出现了一个问题? 这样会出现多重继承的关系,又违背了‘is-a‘ 的原则 怎么办 java语言中可以通过 interface 接口类 来实现多继承 python中本身就支持 多继承的关系。 ‘‘‘ # 交通工具 vehicle class vehicle(): # 运送货物 def huo(self): print(‘运送货物‘) # 搭载乘客 def ren(self): print(‘搭载乘客‘) # 此时去定义一个飞行器的类Flying, 让需要飞行的交通工具,直接继承这个类。可以解决这个问题。 # 但是,1。出现类多继承,违背了‘is-a‘ 2。 飞行器这个类很容易被误解 # 解决方案也是使用多继承,但是给飞行器这个类,定义成为一个Mixin混合类, # 此时就是等于把飞行器这个类,作为了一个扩展的功能,来扩展其它类 # 定义飞行器 class FlyingMixin(): def fly(self): print(‘可以起飞了... ‘) # 定义汽车类 class cart(vehicle): pass # 定义飞机类 class airplane(vehicle,FlyingMixin): pass # 直升机 class helicopter(vehicle,FlyingMixin): pass ‘‘‘ 在上面的代码中,虽然直升机和”飞机都使用了多继承,也就是继承了FlyingMixin 但是由于FlyingMixin 类加了Mixin这个名, 就告诉了后面阅读代码的人,这个类是一个Mixin类 Mixin表示混入(mix-in) Mixin必须是表示一种功能,而不是一个对象。 Mixin的功能必须单一,如果有多个功能,那就多定义Mixin类 python中的Mix in是通过多继承实现的 Mixin这个类通常不单独使用,而是混合到其它类中,去增加功能的 Mixin类不依赖子类的实现,即便子类没有继承这个Mixin,子类也能正常运行,可能就是缺少了一些功能。。 使用Mixin混入类的好处? 1. Mixin 这个混入类的设计模式,在不对类的内容修改的前提下,扩展了类的功能 2. Mixin 混入类为了提高代码的重用性,使得代码结构更加简单清晰 3.可以根据开发需要任意调整功能(创建新的Mixin混入类) 4.避免设计多层次的复杂的继承关系。 ‘‘‘
‘‘‘ 抽象类是一个特殊的类: 1.抽象类不能用,不能直接实例化成为一个对象。 2.抽象类中包含了抽象方法,抽象方法就是没有实现代码的方法。 3.抽象类需要子类继承,并重写父类的抽象方法。才可以使用。 抽象类,一般应用在程序设计,程序设计中一般是要对功能和需求进行规划,其中有一些需求是明确的并且可以完成的, 但是也可能会有一些需求是不明确的,或者不确定具体需要怎么实现, 那么此时就可以把这个不确定怎么实现或者需要后面再去实现的方法,定义为抽象方法(只定义方法名,不写具体代码) 举例: 公司有项新的产品需要开发,交给了开发部门]的老大 这个老大开始会规划设计怎么去完成这个产品的开发, 必须项目需要用到不同的技术,需要不同的人来完成, 这样的话,老大就自己完成来一部分功能, 还有一部分定义了需求,但是没有具体实现,需要其它的人来实现 这样,已经完成的部分就是普通方法,定义来,但是未完成的就可以理解为抽象方法 ‘‘‘ import abc class WriteCode(metaclass=abc.ABCMeta): # 需要抽象的方法,使用装饰器进行装饰 @abc.abstractmethod def write_php(self): pass def write_java(self): print(‘实现了java代码的开发‘) def write_python(self): print(‘实现了python代码的开发‘) # 抽象类不能直接实例化对象 # 定义子类,继承抽象类,并是吸纳抽象类中的抽象方法 class Demo(WriteCode): def write_php(self): print(‘实现了php的开发‘) a = Demo() print(a) a.write_java() a.write_php() a.write_python() ‘‘‘ 抽象类的应用: 例如要开发一个框架,这个框架要有什么什么功能。 但是你具体用这个框架开发什么样的产品,我们并不清楚,因此你想想这个框架中能否知道你要什么样的开发。 框架就具备定的功能既可, 剩下的,需要具体开发项目的人来实现 自己的业务逻辑。 ‘‘‘
原文:https://www.cnblogs.com/yuyunjie/p/13127387.html