day 26面向对象 的封装 接口 抽象

大纲分析

# 面向对象
# 类 :一类具有相同属性和方法的事物
#类的定义: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

#静态方法和类方法 都是直接可以使用类名调用
#普通方法:对象调用
原文地址:https://www.cnblogs.com/xiaoluoboer/p/7881127.html