day31 Pyhton 面向对象的基础 三大特性
一.内容回顾
封装
1.概念 笔记
2.__名字 在类的外部就不能用了
3.私有化的 不能被子类继承,也不能在其他任何类中调用
三个装饰器方法(装饰类中的方法)
1.不被修饰的 普通方法,会使用对象self的属性
2.@classmethod 类方法,不使用self的属性,用类cls的属性
3.@staticmethod 静态方法,不用self的属性和类cls的属性
4.@property 将一个方法伪装成一个属性
def 函数名
@函数名.setter
@函数名.deleter
# from math import pi # class Circle: # def __init__(self,r): # self.r = r # @property # def area(self): # return pi*self.r**2 # @property # def perimeter(self): # 周长 # return 2*pi*self.r # @perimeter.setter # def perimeter(self,新的周长): # self.r = 新的周长 / 2 / pi
setter修改属性值
# setter装饰的函数名叫什么 perimeter
# 那么在这个函数中绝对不可以对这个函数名同名的属性进行修改
# 程序的逻辑问题 # 1. 不可以对某些计算结果直接赋值 # 2. 一般是通过对计算结果产生影响的属性进行重新赋值 # 比如说对于圆这个例子 : 不能直接修改面积或者周长,应该通过修改半径来带动对应周长和面积的改变
# 反射(不得不用) # 使用字符串的方式,操作对象的属性(对象属性,类的动态属性(方法)) # 在python中 一切皆对象(类也是对象,对象也是对象,模块也是对象) # a.b # a就是一个对象 # b本质上是一个变量名,也可以说是a的一个属性 # 如果b是b 那么就用a.b # 如果b是'b' 那么就用getattr(a,'b')
二.面向对象的基础
三大特性
基础的继承
基础的封装 __私有
两个内置函数:issubclass isinstance
反射: setattr/delattr 了解
内置方法: 你没有应用场景
__new__
__call__
__str__/__repr__
__len__
__***item__系列
__hash__
__eq__
issubclass(子类,父类),如果真的有继承关系,就返回True
class A(object):pass class B(A):pass print(issubclass(B,A))
# isinstance(对象,类) # class A(object):pass # a = A() # print(isinstance(a,A))
# # 继承
# class A(object):pass
# class B(A):pass
# b = B()
# print(isinstance(b,A)) # 检测的对象是不是某个类以及其父类的对象
# print(type(b) is B) # 检测的是对象是不是某一个类的实例
# print(type(b) is A)
所有的反射 都是用字符串 操作对象的属性
class A: def __init__(self,name,age): self.name = name self.age = age a = A('alex',83) # hasattr # print(getattr(a,'name'))#alex # a.sex = '不详' # setattr(a,'sex','不详') # print(a.sex)#不详 del a.age # delattr(a,'age') print(a.__dict__)#{'name': 'alex', 'sex': '不详'}
# 关于内置方法的名字 # 内置方法 双下方法 魔术方法 # 内置方法的特点 # 一定有某一个语法或者一种写法自动触发这个方法
# 重点掌握的 # 哪些写法 触发 对应的内置方法 # 实例化 __new__\__init__ 构造方法(单例模式)\初始化方法 # 对象() __call__ # del 对象 __del__ 析构方法\对象删除之前的收尾工作 # print(对象) __str__ 让一个对象的显示更加清晰 # str(对象) # '%s'%对象 # repr() __repr__ 是__str__的备胎,并且还和repr(),%r格式化有关系 # '%r'%对象 # len(对象) __len__ # 对象[参数] item系列 # == __eq__
__call__ 对象用call方法可以调用函数__call__里的方法
# __call__ class Student(): def __init__(self,name,age): self.name = name self.age = age def call(self):pass def __call__(self, *args, **kwargs): print('调用我啦') alex = Student('alex',83) # callable #查看某个变量能否被调用 # callable(变量) #返回True,那么 变量() --> 调用 print(callable(Student))#True print(callable(alex))#True # alex() alex.call()#调用我啦
class Dog(object): def __new__(cls, *args, **kwargs): pass dog_obj = object.__new__(cls)#调用父类object的__new__内置方法 dog_obj = super().__new__(cls)##调用父类object的__new__内置方法,第二种方法 return dog_obj def __init__(self,name,age): self.name = name self.age = age wc = Dog('旺财',2) print(wc.name)
# 一个类 只能实例化一次的方法 class Teacher: flag = None def __new__(cls, *args, **kwargs): if cls.flag is None: cls.flag = object.__new__(cls) # 这一句话只能走一次 return cls.flag def __init__(self,name): self.name = name alex1 = Teacher('alex') alex2 = Teacher('alex') yuan = Teacher('yuan') print(alex2.name)#yuan print(yuan.name)#yuan
__del__
# 析构方法(了解) 删除 class Teacher: def __init__(self,name): self.name = name def __del__(self): print('执行我啦') alex = Teacher('ALEX') del alex print('hahaha')
# del alex # 执行del 对象的时候 触发__del__,在真正的删除alex对象之前,执行的方法__del__ # 如果我们自己不删除alex,那么在程序的执行过程中或者最后,垃圾回收机制会替你执行del alex # 1.del alex # 2.执行__del__ # 3.删除alex
class File(object): def __init__(self,file_name): self.f = open('file_name') def read(self): self.f.read(1024) def __del__(self):# 对象使用的一些操作系统的资源的归还工作/收尾工作 self.f.close()
__str__
class Course: def __init__(self,name,price,period,teacher): self.name = name self.price = price self.period = period self.teacher = teacher def __str__(self): # 必须有返回值,必须返回一个str类型 return '%s,%s,%s,%s'%(self.name,self.price,self.period,self.teacher) course_lst = [] python = Course('python',19800,'6 months','baoyuan') linux = Course('linux',16800,'5 months','oldboy') print(python) print(str(python)) print('课程展示 : %s'%python)
class Course: def __init__(self,name,price,period,teacher): self.name = name self.price = price self.period = period self.teacher = teacher def __str__(self): # 必须有返回值,必须返回一个str类型 return '%s,%s,%s,%s'%(self.name,self.price,self.period,self.teacher) course_lst = [] python = Course('python',19800,'6 months','baoyuan') linux = Course('linux',16800,'5 months','oldboy') print(python) print(str(python)) print('课程展示 : %s'%python)
# list.__str__() l = [1,2,3,4] # 对象 列表的对象 print(l) print('[%s,%s,%s]'%(l[0],l[1],l[2]))
__repr__ 是str方法的备胎(有str调用str,没有str走repr)
class Course: def __init__(self,name,price,period,teacher): self.name = name self.price = price self.period = period self.teacher = teacher def __repr__(self): # 必须有返回值,必须返回一个str类型 return 'repr --> : %s,%s,%s,%s'%(self.name,self.price,self.period,self.teacher) def __str__(self): # 必须有返回值,必须返回一个str类型 return 'str --> : %s,%s,%s,%s'%(self.name,self.price,self.period,self.teacher) python = Course('python',19800,'6 months','baoyuan') linux = Course('linux',16800,'5 months','oldboy') print(python) print(linux)
class Course: def __init__(self,name,price,period,teacher): self.name = name self.price = price self.period = period self.teacher = teacher def __repr__(self): # 必须有返回值,必须返回一个str类型 return 'repr --> : %s,%s,%s,%s'%(self.name,self.price,self.period,self.teacher) def __str__(self): # 必须有返回值,必须返回一个str类型 return 'str --> : %s,%s,%s,%s'%(self.name,self.price,self.period,self.teacher) python = Course('python',19800,'6 months','baoyuan') linux = Course('linux',16800,'5 months','oldboy') print('%r'%python)#repr --> : python,19800,6 months,baoyuan print('%s'%python)#str --> : python,19800,6 months,baoyuan print(str(python))#str --> : python,19800,6 months,baoyuan print(repr(python))#repr --> : python,19800,6 months,baoyuan
# 流畅的python : repr和str 如果只能写一个的 写repr
class Course: def __init__(self,name,price,period,teacher): self.name = name self.price = price self.period = period self.teacher = teacher def __len__(self): return len(self.__dict__) def __getitem__(self,item): return self.__dict__[item] def __setitem__(self, key, value): self.__dict__[key] = value def __delitem__(self, key): self.__dict__.pop(key) python = Course('python',19800,'6 months','baoyuan') print(len(python)) print(python.name) print(python['name']) # ==> 调用getitem print(python['price']) # ==> 调用getitem python['name'] = 'python2.0' print(python.name) # del python.name#与下一句功能一样 del python['name'] print(python.__dict__)#{'price': 19800, 'period': '6 months', 'teacher': 'baoyuan'} # 有一些内置的函数/模块 要想能正确的使用它们 那么必须按照它规定的语法来实现
__len__ 测量对象长度
class Ruler: def __init__(self,price,length,jingdu): self.length = length self.price = price self.jingdu = jingdu def __len__(self): return self.length stu_ruler = Ruler(2.5,15,0.1) print(len(stu_ruler))#15
__eq__ s1==s2 等于 s1.__eq__(s2)
class Student(): def __init__(self,name,age): self.name = name self.age = age def __eq__(self, other): if self.name == other.name and self.age == other.age: return True return False s1 = Student('贾卫东',20) s2 = Student('贾卫东',20) print(s1 == s2) # s1.__eq__(s2)#True print(s1 is s2) # s1.__eq__(s2)#False
#够通过这个字符串 --> 程序中的变量名(类名\函数名\变量名\方法名\对象名)
class Manager:pass class Student:pass class Teacher:pass identify = 'Student' print(eval(identify)())#<__main__.Student object at 0x00000000025657B8>
反射 hasattr getattr
class Person: role = '人类' Country = '中国' attr = input('>>>') # role 人类 # # Country 中国 print(getattr(Person,'role')) print(getattr(Person,'Country')) if hasattr(Person,attr): print(getattr(Person,attr)) if attr == 'role': print(Person.role) elif attr == 'Country': print(Person.Country)
class Person: role = '人类' @staticmethod def show_courses(): print('所有课程')
# 反射类中的方法 # class Person: # role = '人类' # @staticmethod # def show_courses(): # print('所有课程') # Person.role == getattr(Person,'role') # Person.show_courses() == getattr(Person,'show_courses')() # ret = getattr(Person,'show_courses') # ret()
# 有一个类,有很多静态属性,也有很多静态方法/类方法 # 用户输入input任意的属性名或者方法名, # 如果是属性 直接打印 - 用到一个内置函数#getattr(Person,'role') # 如果是方法 直接调用 - 用到一个内置函数#getattr(Person,'show_courses') # 要求程序不报错