抽象类:本身不能被实例化,也不应该不实例化,它的作用就定义标准,并不用具体实现
import abc
class Parent(metaclass=abc.ABCMeta):
x=1
@abc.abstractmethod
def foo(self):
pass
@abc.abstractmethod
def bar(self):
pass
class Child(Parent):
def foo(self):
pass
def bar(self):
pass
新式类与经典类在这种继承结构下,属性的查找顺序完全一样:从做到右,一个分支接着一个分支地找
print(mro()) # 查看属性查找顺序,只在新式类中适用
新式类的在这中继承结构下,属性的查找关系,H->E->B->F->C-G-D-A 广度优先
经典类的在这中继承结构下,属性的查找关系H-E-B-A-F-C-G-D 深度优先
子类调用父类的方法,uper()函数
class People:
def __init__(self,name,age,sex):
self.name = name
self.age = age
self.sex = sex
def foo(self):
print('from parent')
class Teacher(People):
def __init__(self,name,age,sex,salary,level):
# People.__init__(self,name,age,sex) # 指名道姓地调用People类的__init__函数
# 在python3中
super().__init__(name,age,sex) # 调用父类的__init__的功能,实际上用的是绑定方法
# super()函数一般只用于继承一个父类,如果是多个父类,只能找一个,多个的话,还是用指名道姓的方法
# 在python2中
# super(Teacher,self).__init__(name,age,sex)
self.salary = salary
self.level = level
def foo(self):
super().foo()
print('from child')
t = Teacher('egon',18,'male',3000,10)
print(t.name,t.age,t.sex,t.salary,t.level)
t.foo()
封装
*封装数据
*封装功能
class Teacher:
__school = 'oldboy' # _Teacher__school
def __init__(self,name,salary):
self.name = name
self.__salary = salary
def __foo(self):
print('====>')
t = Teacher('egon',3000)
# python里面没有绝对的封装
# print(t.__school) # 不能调用
print(Teacher.__dict__) # 查看后发现变形了
print(t._Teacher__school) #可以查看变形后的
t._Teacher__foo()
# 这种变形操作只在定义阶段发生
Teacher.__N = 12345
print(Teacher.__dict__) # 没有变形
在类的外部,无法直接使用变形的属性,但是在类的内部可以直接使用
class Teacher:
__school = 'oldboy' # _Teacher__school
def __init__(self,name,salary):
self.name = name
self.__salary = salary #self._Teacher__salary
def foo(self):
print('====>',self.__salary) # 这里直接调用了,所以外部t.foo()有结果
t = Teacher('egon',3000)
print(t._Teacher__salary)
t.foo()
一个例子
class A:
def foo(self):
print('from A.foo')
self.__bar() #self._A__bar()
def __bar(self): #_A__bar()
print('from A.bar')
class B(A):
def __bar(self): #_B__bar
print('from B.bar')
pass
b = B()
b.foo()
封装应用
class People:
def __init__(self,name,age,sex,height,weight):
self.__name = name
self.__age = age
self.__sex = sex
self.__height = height
self.__weight = weight
def tell_name(self):
print(self.__name)
def set_name(self,val):
if not isinstance(val,str):
raise TypeError('名称必须为字符串类型')
self.__name = val
def tell_info(self):
print('''
---------%s info--------
NAME:%s
AGE:%s
SEX:%s
HEIGHT:%s
WEIGHT:%s
''' %(self.__name,
self.__name,
self.__age,
self.__sex,
self.__height,
self.__weight))
egon = People('egon',18,'mail','178cm','70kg')
egon.tell_name()
egon.tell_info()
egon.set_name('EGON')
# egon.set_name(123)
egon.tell_info()
property的应用
定义People类,将name,age,sex,height,weight属性都隐藏起来
对外提供接口,可以访问人的详细信息
对外提供访问姓名,修改姓名,删除姓名的接口,在修改姓名时加上类型检查
对外提供接口,访问人的BMI指数,并且用property装饰
class People:
def __init__(self,name,age,sex,height,weight,permission=False):
self.__name = name
self.__age = age
self.__sex = sex
self.__height = height
self.__weight = weight
self.permission = permission
@property
def info(self):
print('''
---------%s info--------
NAME:%s
AGE:%s
SEX:%s
HEIGHT:%s
WEIGHT:%s
''' %(self.__name,
self.__name,
self.__age,
self.__sex,
self.__height,
self.__weight))
@property
def dmi(self):
print(self.__weight / (self.__height ** 2))
@property
def name(self):
print(self.__name)
return self.__name
@name.setter
def name(self, val):
if not isinstance(val, str):
raise TypeError('must be str')
self.__name = val
@name.deleter
def name(self):
if not self.permission:
raise PermissionError('do not del')
del self.__name
egon = People('egon',18,'mail',78,70)
egon.info
egon.dmi
egon.info
egon.name = 'EGON'
# del egon.name
egon.info