大纲分析 # 面向对象 # 类 :一类具有相同属性和方法的事物 #类的定义:class #类中可以定义的方法种类: #普通方法 self 对象 #类方法 cls @classmethod 类/对象 #静态方法 @staticmethod 类/对象 #属性方法 self @property 对象 #私有方法 self __方法名 self/cls #类中可以定义的属性: 静态属性 类 # 对象 #实例化 : 类名() #创造对象 #初始化对象 __init__ #返回一个对象 #对象的属性: # 普通属性 对象 # 私有属性 __属性名 self #属性的操作 #增 对象名.新属性名 = 值 #删 del 对象名.属性名 #改 对象名.属性名 = 新值 #查 对象名.属性名 #组合 : 一个类的对象作为另一个类对象的属性;什么有什么 #继承 : 解决代码的复用,提取公共代码到父类;什么是什么 # 单继承和多继承 # 子类继承了父类除了私有的之外的所有属性和方法 # 子类执行方法的查找顺序: # 经典类中:先找自己,自己没有找父类,遵循深度优先 # 新式类中:先找自己,自己没有找父类,遵循广度优先 # 子类执行父类的方法: #1.指名道姓 指到谁就是谁 父类名.父类中的方法名(self) #2.super 只能在新式类中使用,且找的顺序是mro顺序 super(子类名,子类对象名).方法名() # *** 抽象类和接口类 #@abstractmethod #多态 # python 天生多态 #崇尚鸭子类型 : 不需要通过继承关系就实现对相似的功能
# 封装 # 【封装原则】 # 1. 将不需要对外提供的内容都隐藏起来; # 2. 把属性都隐藏,提供公共方法对其访问。 # 私有变量和私有方法 # 在python中用双下划线开头的方式将属性隐藏起来(设置成私有的) # 针对变量属性x (静态或者动态 ) __x 相当于 _类名__x # 封装 :把一些属性和方法放到类里 这本身就是一种封装 # 封装 : 把属性和方法藏在类里 我只能在类内部调用,不能再外部使用 #1 私有属性之一 私有的对象属性 # class Room: # def __init__(self,name,price,length,width): # self.name = name # self.price = price # self.__length =length #私有的对象属性 # self.__width = width # # def area(self): # return self.__length*self.__width # # house = Room('小超超',1000000,2,1) # print(house.area()) # 私有属性能不能继承 不能继承 因为上级的 _A__func 这一级 是 _B__FUNC # 定义一个私有变量\属性\方法 : __名字 #在类的内部可以直接用 : __名字 #在类的外部不能直接使用,如果一定要用,在私有方法之前加上:_类名,变成 _类名__名字 #在类外的名字 通过__dict__就可以查看不建议 # class A: # def func(self): # fun() # print('__a_func') # # class B(A): # def __init__(self): # self.func() # func() # print(11) # b = B() # __a_func # 11 # 这样的情况 self.func() 变成 b.func() 被A func(b)调用 继承了A 先打印 后打印11 # class A: # def __func(self): #_A__func() # print('__a_func') # # class B(A): # def __init__(self): # self.__func() # _B__func() # def __func(self): # print(11) # b = B() # # 11 # 因为父级A 是 _A__func() ,子集B 是_B__func() 函数名不一样所以不能继承A父类的 # 但是下边的函数名是一样的。 # 此时 b._B__func() # -------------- # property # @property 把一个方法 伪装成一个属性 直接用就行了 在方法上加上@property #1.属性的值 是这个方法的返回值 #2.这个方法不能有参数了 只能有self # 公有的 #私有的 + property # class Person: # def __init__(self,name,height,weight): # self.name = name # self.height = height # self.__weight = weight # # @property # def bmi(self): # return self.__weight / (self.height ** 2) # # li = Person('李岩',1.75,65) # print(li.bmi) # # # 圆形类 : 面积 周长 # from math import pi # class Circle: # def __init__(self,r): # self.r = r # @property # def area(self): # return self.r*self.r*pi # # @property # def perimeter(self): # return self.r*pi*2 # c1 = Circle(5) # print(c1.area) # print(c1.perimeter) # #圆形类 : 面积 周长 property 的应用 # from math import pi # class Circle: # def __init__(self,r): # self.r = r # @property # def area(self): # return self.r*self.r*pi # # @property # def perimeter(self): # return self.r*pi*2 # c1 = Circle(5) # print(c1.area) # print(c1.perimeter) # 很重要的实例 # 1简单的打折 # class Goods: # discount = 0.8 # def __init__(self,name,price): # self.name = name # self.__price = price # @property # def price(self): # return self.__price*Goods.discount # app = Goods('苹果',10) # print(app.price) # # #如没有哪个伪装属性@propetry 必须打印app.price() # app.price = 6 不能改变 因为里面是私有的 # print(app.price) # 2题目组合propety 组合setter,修改改变价格为6元 # 注意事项 修改的价格时候搭配 方法上面@property # 下边的同一个属性上面@属性.setter () 前提必须有prooety # 注意这个属性必须前后是一种 # class Goods: # __dicount = 0.8 # def __init__(self,name,price): # self.name = name # self.__price = price # @property # def price(self): # return self.__price*Goods.__dicount # @price.setter #装饰器 # def price(self,new_price): # if type(new_price) is int: # 这个或者时float # self.__price = new_price # app = Goods('苹果',10) # app.price = 6 # setter # print(app.price) # property # 注意装饰器的调用没有返回值的话 直接调用就空 # 封装 # __私有+property #让对象的属性变得更安全了 #获取到的对象的值可以进行一些加工 #修改对象的值的同时可以进行一些验证 # class Foo: # @property # def AAA(self): # print('get的时候运行我啊') # # @AAA.setter # def AAA(self,value): # print('set的时候运行我啊') # # @AAA.deleter # def AAA(self): # print('delete的时候运行我啊') # # #只有在属性AAA定义property后才能定义AAA.setter,AAA.deleter # f1=Foo() # print(f1.AAA) #property 为什么是None 在打印这个属性 只是调用没有返回 # f1.AAA='aaa' #setter # del f1.AAA #deleter # 删除名字 先@property 后 @deleter 里面删除 外边在删除 # class Goods: # __discount = 0.8 #静态属性 # def __init__(self,name,price): # self.__name = name # self.__price = price #原价 # @property # def name(self): # return self.__name # # @name.setter # def name(self,new_name): # self.__name = new_name # # @name.deleter # def name(self): # del self.__name # @property # def price(self): #折后价 # return self.__price * Goods.__discount # # @price.setter # def price(self,new_price): #修改原价 # if type(new_price) is int: # self.__price = new_price # apple = Goods('苹果',10) # apple.price = '10' #settrt # print(apple.price) #property # del __self.name # print(apple.name) # --------- #私有的 #私有的静态属性、方法、对象属性 #使用__名字的方式调用,保证在类内部可以调用,外部不行 #私有的 不能被继承 # 当有一个名字,不想被外部使用也不想被子类继承,只想在内部使用的时候就定义私有的 #私有的 #私有的静态属性、方法、对象属性 #使用__名字的方式调用,保证在类内部可以调用,外部不行 #私有的 不能被继承 # 当有一个名字,不想被外部使用也不想被子类继承,只想在内部使用的时候就定义私有的 # class D: # def __init__(self): # print('d') # class C(D): # def __init__(self): # print('c') # super().__init__() # class B(D): # def __init__(self): # print('b') # super().__init__() # class A(B,C): # def __init__(self): # print('a') # super().__init__() # #mro # a = A() # print(A.mro()) # from math import pi # class Circle: # def __init__(self,circle_r): # self.circle_r = circle_r # def perimetre(self): # return 2*pi*self.circle_r # def area(self): # return pi*self.circle_r**2 # class Rings: # def __init__(self,d_R,d_r): # self.d_R = Circle(d_R) # self.d_r = Circle(d_r) # # # Circle()这个是圆的对象 左边的是属性 Rings这个类 以Circle这个类的对象为属性 叫组合 # @property # def ring_perimetre(self): # return self.d_R.perimetre()+self.d_r.perimetre() # @property # def ring_area(self): # return self.d_R.area()-self.d_r.area() # ring = Rings(10,5) # print(ring.ring_perimetre) # print(ring.ring_area) # # class A: # __N=0 #类的数据属性就应该是共享的,但是语法上是可以把类的数据属性设置成私有的如__N,会变形为_A__N # def __init__(self): # self.__X=10 #变形为self._A__X # def __foo(self): #变形为_A__foo # print('from A') # def bar(self): # self.__foo() #只有在类内部才可以通过__foo的形式访问到. # a = A() # print(A._A__foo())??????????????? # A._A__N # 外边访问内部 是可以访问到的,即这种操作并不是严格意义上的限制外部访问,仅仅只是一种语法意义上的变形 # print(A._A__N ) #外边访问内部 语法没问题 但是不能这么用 # 1. # 类中定义的__x只能在内部使用,如self.__x,引用的就是变形的结果。 # 2. # 这种变形其实正是针对外部的变形,在外部是无法通过__x这个名字访问到的。 # 3. # 在子类定义的__x不会覆盖在父类定义的__x,因为子类中变形成了:_子类名__x, 而父类中变形成了:_父类名__x,即双下滑线开头的属性在继承给子类时,子类是无法覆盖的。 # property属性 @property 在方法的前面 上面加上这个 底下的方法就变成属性了 # 打印的时候就是直接打印方法 而不需要方法加上括号了 # 复制代码 # class People: # def __init__(self,name,weight,height): # self.name=name # self.weight=weight # self.height=height # @property # def bmi(self): # return self.weight / (self.height**2) # # p1=People('egon',75,1.85) # print(p1.bmi) # 什么是特性property # # property是一种特殊的属性,访问它时会执行一段功能(函数)然后返回值 #------------------- #接口定义:是规范子类的一个模板,只要接口类定义的,就应该在子类中实现。 # 接口类 不能被继承 就是父类就不能被继承, # 自己理解 接口类 模板 是针对 子类的方法不一样的而抛出异常, # 让其继承父类的方法,需要定义一个函数和一个新的父类 # # 第一种比较low的那种 # class Payment: #定义一个父类 为解决 子类的方法不统一 # def pay(self,money): raise NotImplementedError #主动刨出异常 # # class Apple_pay(Payment): # def pay(self,money): # print('请使用苹果支付了%s元'% money) # # class Ali_pay(Payment): # def pay(self, money): # print('请使用支付宝支付了%s元' % money) # # class Wechat_pay(Payment): # def fukuan(self, money): # print('请使用苹果支付了%s元' % money) # def pay (obj,money): #定义的函数和父类的方法必须一致才会检测通过的, # return obj.pay(money) # ap = Apple_pay() # al =Ali_pay() # we = Wechat_pay() # pay(ap,100) # pay(we,200) # 接口2 固定用法 自动检测异常的 如果子类不能继承父类就异常 接口类不能被继承 # 如果有两个@abstractclassmethods 两个都会检测 必须符合两个才不会抛出异常 # from abc import ABCMeta,abstractmethod # 父类(metaclass=ABCMeta) # 在父类方法上面装饰 @abstractmethod # from abc import ABCMeta,abstractmethod # class Payment(metaclass=ABCMeta): #定义一个父类 为解决 子类的方法不统一 metaclass元类 # @abstractmethod # def pay(self,money):pass # @abstractmethod # def ger(self,money):pass # class Apple_pay(Payment): # def pay(self,money): # print('请使用苹果支付了%s元'% money) # # class Ali_pay(Payment): # def pay(self, money): # print('请使用支付宝支付了%s元' % money) # # class Wechat_pay(Payment): # def fukuan(self, money): # print('请使用苹果支付了%s元' % money) # def pay (obj,money): #定义的函数和父类的方法必须一致才会检测通过的, # return obj.pay(money) # ap = Apple_pay() # # al =Ali_pay() # # we = Wechat_pay() # pay(ap,100) # pay(we,200) # wechat 因为和父类方法不一样 所以就异常 # 题目三 如果父类有两个方法 那字类也必须继承父类两个方法 否则报错 。 # 接口类: # 是规范子类的一个模板,只要接口类中定义的,就应该在子类中实现 # 接口类不能被实例化,它只能被继承 # 支持多继承 # —————————————————————————— # 定义一个类 #类里面的方法 #并没有用到self # 类方法 改变一个静态的属性 # class Goods: # __discount = 0.8 # @classmethod # def change_discount(cls,new_discount): # cls.__discount = new_discount # @classmethod # def get_discount(cls): # return cls.__discount # Goods.change_discount(0.75) # print(Goods.get_discount()) #类方法 #调用:不需要实例化 直接用类名调用就好 #定义:不用接受self参数,默认传cls,cls就代表当前方法所在的类 #什么时候用类方法? #需要使用静态变量 且 不需要和对象相关的任何操作的时候 #静态方法 #如果这个方法 既不需要操作静态变量 # 也不需要使用对象相关的操作, # 就使用静态方法 # class A: # @staticmethod # def func(name): #静态方法 # print(123) # A.func('alex') #面向对象编程:专门为面向对象编程提供的一个方法——staticmethod #它完全可以当做普通函数去用,只不过这个函数要通过类名.函数名调用 #其他 传参 返回值 完全没有区别 #类里面,一共可以定义这三种方法: #普通方法 self #类方法 cls #静态方法 #绑定方法 和 非绑定方法 # class A: # @staticmethod # def func1(name): #静态方法 # print(123) # # @classmethod # def func2(cls): # 静态方法 # print(123) # # def func3(self):pass # a = A() # print(a.func1) #静态方法 # print(a.func2) #类方法 : 绑定到A类的func # print(a.func3) #普通方法:绑定到A类对象的func #静态方法和类方法 都是直接可以使用类名调用 #普通方法:对象调用