class Father:
__secrect="xxx"
story='从前有座山...'
def tellAstory(self):
print("我的故事:",self.story)
def __tellAstory(self):
#访问prvite属性的时候,需要使用类名进行访问
print("我的密码:",Father.__secrect)
#继承Father类
class Son(Father):
def tell(self):
#继承父类
#强行调用父类的私有属性
Father._Father__tellAstory()
self.tellAstory()
# 3.覆盖/重写
# 子类和父类有相同名称和方法
# 可以理解为子类对于父类行为的扩展或者补充
class Pet:
def __init__(self,name):
self.name=name
print(f"一个名叫{self.name}的宠物出生了")
def eat(self):
print(f"{self.name}在吃东西....")
class Dog(Pet):
def lookAfter(self):
print(f"{self.name}在看门")
def eat(self):
print(f"{self.name}在啃骨头")
子类在定义的时候,可以使用supper()调用父类的方法
class Cat(Pet):
#应用2:对象初始化时,简化重复属性的赋值
def __init__(self,name,age,sex):
#self.name=name
#self.age=age
#self.sex=sex
#print(f"一个名叫{self.name}的宠物出生了")
#这种方式的代码重复度较大,采用supper()来调用父类
#supper(Cat,self).__init__(name)
super().__init__(name)
self.gae=age
self.sex=sex
def eat(self):
#self.cat()#不能这样去调用父类的eat()对象,默认是死循环
super().eat()#调用父类的eat()对象
print(f"{self.name}吃完东西后,用唾液洗洗脸")
#子类可以有多个父类
#例如:狗是脊椎动物,哺乳动物,宠物:
#访问子类的属性或方法时,解析的路径:
class Father:
def getMoney(self):
priint("父亲给了零花钱....")
class Mother:
def getMoney(self):
print("母亲给了零花钱....")
#继承Father和Mother
class Child(Father,Mother):
def getMoney(self):
super().getMoney()
print("孩子有了零花钱...")
输出:父亲给了零花钱....
孩子有了零花钱....
#假设Father类没有getMoney函数
class GrandFather:
def getMoney(self):
priint("爷爷给了零花钱....")
class Father(GrandFather)
pass
class Mother:
def getMoney(self):
print("母亲给了零花钱....")
#继承Father和Mother
class Child(Father,Mother):
def getMoney(self):
super().getMoney()
print("孩子有了零花钱.....")
#输出:
#爷爷给了零花钱....
#孩子有了零花钱.....
########################################
子类调用父类时,调用对象的顺序是深度优先
########################################
#打印子类查找顺序的方法
print(Child.mro())
#输出:
<class '__main__.Child'>,<class '__main__.Father'>,<class '__main__.GrandFather'>,<class '__main__.Mother'>,<class 'object'>,
#为什么结尾都是object?
#所有内置的对象的父类,万物皆对象,因为所有的类都是继承object类
#菱形继承
Human
|
|---------|
Faher Mother
|---------|
|
Child
class Human:
def __init__(self):
print("人类.......")
class Father(Human):
def __init__(self):
print("父亲初始化....")
super().__init__()
print("父亲初始化结束....")
class Mother(Human):
def __init__(self):
print("母亲初始化....")
super().__init__()
print("母亲初始化结束....")
class Child(Father,Mother):
def __init__(self):
print("孩子初始化....")
super().__init__()
print("孩子初始化结束....")
c=Child()
按照原来的理解方式:
输出:
#孩子初始化....
#父亲初始化....
#人类.......
#父亲初始化结束....
#孩子初始化结束....
而实际的输出为:
#孩子初始化....
#父亲初始化....
#母亲初始化....
#人类.......
#母亲初始化结束....
#父亲初始化结束....
#孩子初始化结束....
查找基础顺序
print(child.mro())
########################################
初始化是广度优先遍历
########################################
概念:一种类的多种形态
同一行为具有多个不同表现形态或形式的能力。是指一个类实例(对象)的相同方法在不同情形下有不同的表现形式
通过继承的方式实现
1.让程序能够有更强的灵活性
2.让程序能够有更好从适应性
class Animal:
def eating(self):
print("动物下在吃东西.....")
class Pet(Animal):
def eating(self):
print("宠物在吃东西.....")
class Dog(Pet):
def eating(self):
print("狗在啃骨头.....")
class Cat(Pet):
def eating(self):
print("猫在吃鱼....")
class Zoo:
def animallEating(self,animal):
if isinstance(animal,Animal):
print("这是展示动物吃东西的地方:")
else:
print("这是非动物吃饭的展示")
animal.eating()
python特有的方式实现
没有继承关系,但是具备有相同的特征/方法,也可以直接使用.
继续在上面的代码后面追加定义:
class venusFlytrap:
def eating(self):
print("捕蝇草在吃小虫子.....")
v=venusFlytrap()
z=Zoo()
#z是Zoo类但是可以调用venusFlytrap类的对象
z.animallEating(v)
#这里传入的是v,在调用animallEating时需要调用eating对象
#而venusFlaytrap类也具有对象eating,在python中可以直接调用
#即便两个类之间没有继承关系,也可以调用
#判断类型时,只看直接类型
#type是严格满足类型
print(type(c) is Cat) #True
print(type(c) is Animal) #False
print(type(c) is Pet) #False
#isinstance 判断对象是否为一个类型的实例
# 判断实例类型时,涵盖父类的类型
print("*"*30)
print(isinstance(c,Cat)) #True
print(isinstance(c,Pet)) #True
print(isinstance(c,Animal)) #True
print(isinstance(v,Animal)) #False
class Dog:
legs=4
teeth=42
#类方法
@classmethod
def printInfo(cls):
print(f"狗有{cls.legs}条腿,{cls.teeth}颗牙齿")
d=Dog()
d.printInfo()
Dog.printInfo()
静态方法
#静态方法:用@staticmethod装饰的不带self参数的方法叫做静态方法
# 类的静态方法可以没有参数,可以直接使用类调用
class dog:
@staticmethod
def bark(self):
print("wangwang!")
d=Dog()
d.bark()