封装
封装分为两种:
1、广义封装:封装到对象中的属性称为广义封装
2、狭义封装:封装到类或对象中不可在外部调用的变量属性或方法称为狭义封装
类分为两部分:
1、静态变量(静态字段)部分
2、方法部分
示例1
class Person: chara = '穿衣服' # 这部分称为静态变量或静态字段 def __init__(self,name,age): # 这部分称为方法 self.name = name self.age = age
每个部分又分许多小部分:
示例2
class Person: chara = '穿衣服' # 公有静态变量 __breed = '黄皮肤' # 私有静态变量 def __init__(self,name,age): # 普通方法(构造方法) self.name = name # 公有对象属性 self.__age = age # 私有对象属性 def eat(self): # 公有方法 print('人都需要吃饭补充能量') def __work(self): # 私有方法 pass 私有方法:在类外部不能被调用,只有在类内部才能调用。 公有方法:在任何地方都能被调用。 p = Person('eric',100) print(p.chara) print(p.breed) AttributeError: 'Person' object has no attribute 'breed' print(p.__breed) AttributeError: 'Person' object has no attribute '__breed' 想在外部访问__breed怎么办? print(p._Person__breed) # 黄皮肤,虽然这种方法能够访问到类里面的私有类型的内容,但是在以后的编程中不能这么用。
私有类型的内容只能在类的内部去调用,例如在类内部调用__breed这个静态变量。
class Person: chara = '穿衣服' # 公有静态变量 __breed = '黄皮肤' # 私有静态变量 def __init__(self,name,age): # 普通方法 self.name = name # 公有对象属性 self.__age = age # 私有对象属性 def __work(self): # 私有方法 print('他的工作是鉴黄师') def meth(self): print(self.__age) # 查看age的值 self.__work() # 调用私有方法,查看里面的内容 print(self.__breed) p = Person('eric',100) p.meth() 100 他的工作是鉴黄师 黄皮肤
子类同样不能访问父类中的私有静态变量或方法
在类的执行时,将类加载到内存时,类内部有__变量名这样的方法,在python解释器中,都会被解释成 _类名__变量名 这样的格式
练习题:
BMI指数(BMI是计算而来的,但很明显它听起来像是一个属性而非方法,如果我们将其做成一个属性,更便于理解) 成人的BMI数值: 过轻:低于18.5 正常:18.5-23.9 过重:24-27 肥胖:28-32 非常肥胖, 高于32 体质指数(BMI)=体重(kg)÷身高^2(m) EX:70kg ÷(1.75×1.75)=22.86 class BMI: def __init__(self,height,weight): self.__height= height self.__weight = weight def value(self): BMI = self.__weight / (self.__height**2) # 对象的私有属性只能在类的内部调用 return BMI b = BMI(1.74,62) print(b.value())
接口类和抽象类
抽象类和接口类是一种规范,一种写代码时的规范,在接口类中,定义了一些接口名并且并未实现接口的功能,子类继承接口类,并且实现接口的功能
接口类:(模拟支付接口)
第一版: class Wechat_pay(Pay_regulations): def pay(self,money): print('您通过微信支付%s元' %money) class Alipay(Pay_regulations): def pay(self,money): print('您通过支付宝支付%s元' %money) w = Wechat_pay() w.pay(200) a = Alipay() a.pay(100) 缺点:每实例化一次,就要传一次值,类多了的话,就会显得很繁琐 第二版: class Wechat_pay(Pay_regulations): def pay(self,money): print('您通过微信支付%s¥' %money) class Alipay(Pay_regulations): def pay(self,money): print('您通过支付宝支付%s¥' %money) def pay(obj,money): obj.pay(money) w = Wechat_pay() a = Alipay() 优点:统一了支付规则,归一化设置。 第三版: class Pay_regulations: # 定义一个父类,作为规范 def pay(self,money):pass class Wechat_pay(Pay_regulations): # 每个接口继承父类的规范 def pay(self,money): print('您通过微信支付%s元' %money) class Alipay(Pay_regulations): def pay(self,money): print('您通过支付宝支付%s元' %money) def pay(obj,money): obj.pay(money) w = Wechat_pay() a = Alipay() pay(a,400) pay(w,300)
接口提取了一群类共同的函数,可以把接口当做一个函数的集合。
然后让子类去实现接口中的函数。
这么做的意义在于归一化,什么叫归一化,就是只要是基于同一个接口实现的类,那么所有的这些类产生的对象在使用时,从用法上来说都一样。
归一化,让使用者无需关心对象的类是什么,只需要的知道这些对象都具备某些功能就可以了,这极大地降低了使用者的使用难度。
抽象类:
第四版: from abc import ABCMeta,abstractmethod # 导入接口类的必要模块,作用:让定义的接口强制按照这个规范去执行,不按规范执行就会报错,这种格式就表示的是抽象类。 class Pay_regulations(metaclass=ABCMeta): @abstractmethod def pay(self,money):pass class Wechat_pay(Pay_regulations): def pay(self,money): print('您通过微信支付%s元' %money) class Alipay(Pay_regulations): def pay(self,money): print('您通过支付宝支付%s元' %money) def pay(obj,money): obj.pay(money) w = Wechat_pay() a = Alipay() pay(a,400) pay(w,300)
与java一样,python也有抽象类的概念但是同样需要借助模块实现,抽象类是一个特殊的类,它的特殊之处在于只能被继承,不能被实例化
如果说类是从一堆对象中抽取相同的内容而来的,那么抽象类就是从一堆类中抽取相同的内容而来的,内容包括数据属性和函数属性。