封装
封装就是将我们的将一些共有的属性和方法存放到一个类中,这就是所谓的封装
案例:
# 创建一个人的类
class Persion():
def __init__(self):
# 封装了一个name的属性
self.name = "小明"
# 封装了一个跑饿方法
def run(self):
print(f"{self}正在跑")
# 创建对象
p1 = Persion()
p2 = Persion()
p2.name = "小红"
print(p1.name)
print(p2.name)
结果:
在封装中,我们有一个私有权限,就是将你的方法和属性私有化
# - 私有属性或者私有方法,不能被继承,也不能在类的外部进行使用
# - 想要让属性或方法私有,就在类的内部创建属性或者方法的地方,在属性或方法名前增加两个下划线即可
# - 如果想要在类的外部调用私有属性或者私有方法,需要借助非私有方法在类的内部调用
class Person(object):
def __init__(self, name, age):
self.name = name
self.__age = age
# 给私有打开出口
def get_age(self):
# 内部是可以使用私有属性的
return self.__age
# 修改私有属性
def set_age(self, age):
self.__age = age
class Son(Person):
def print_Person(self):
print(self.name)
# 发现调用不了,
# print(self.age)
p = Person('mao',18)
# 发现也调用不了
# print(p.age)
# 如果想要使用私有属性或方法,可以借助方法,在类的内部调用私有属性,或者私有方法
print(p.get_age())
p.set_age(25)
print(p.get_age())
继承
继承就是我们一个类继承另一个类,当我们继承了这个了后,我们就也可以使用这个类的方法和属性了。
继承有分为但继承和多继承。
单继承
单继承就是继承一个父类,也就是所谓的一个儿子有一个爹
案例:
# 定义父类
class Person(object):
def __init__(self,name):
self.name = name
def run(self):
print('父亲正在跑')
# 儿子继承父亲
class Son(Person):
pass
# 实例对象
# 此刻发现儿子继承了父亲的属性
s = Son("小明")
# 此刻发现儿子也有父亲的方法
s.run()
我们发现我们Son没有定义方法但是却可以调用方法了,这个就体现出了继承的好处,我们有定义任何东西,但是我就是可以调用,ai,就是这么牛逼
多继承
多继承就是我们继承了很多的父类,但是这个有点违背了我们人类的思想,我们可以这样理解,知识继承了一个父类,但是后面觉得这个父类有点孤单,又认了多个干爹,让这个父类不再那么孤单
案例:
class Person(object):
def eat(self):
print("我猜你一定会吃饭的")
class Father(Person):
def game(self):
print("老年倍棒,我要吃鸡")
class Mother(Person):
def sing(self):
print("来一个最炫民族风")
class Son(Father,Mother):
pass
# 多继承时候子类可以调用多个父类非私有的功能
s = Son()
s.game()
s.sing()
s.eat()
结果:
我们发现此刻明明Son明明没有定义这么多方法,但是却可以调用,这就是我们多继承的好处。
在多继承中,如果多个父类有相同的方法,我们应该先调用哪一个呢?
案例:
class Person(object):
def eat(self):
print("我猜你一定会吃饭的")
class Father(Person):
def game(self):
print("老年倍棒,我要吃鸡")
def sing(self):
print("来一个小苹果")
class Mother(Person):
def game(self):
print("老年倍棒,我要王者")
def sing(self):
print("来一个最炫民族风")
class Son(Father,Mother):
pass
# 子类继承多个父类时候,父类有相同的方法,会调用哪一个呢?
# 优先调用 Father,
s = Son()
s.game()
s.sing()
结果:
结论:我们在继承多个父类时候,我们会先继承左边的那个父类,如果左边的没有我们会继续寻找右边的父类,如果组后都没有找到,就会报错
重写:
我们子类既继承了父类,但是自己也想用自身和父类同名的方法,那样会怎样呢?
当我们子类的方法名和父类的只要一样,那么在python中就是重写。
重写就是我们将父类的方法给覆盖了,将自己的动作行为覆盖上去
案例:
# 定义一个人的类
class Person(object):
def eat(self):
print("人在吃东西给")
class Father(Person):
# 重写方法
def eat(self):
print("我继承了人的类,现在我在吃东西")
# 创建都西昂
f = Father()
# 调用方法
f.eat()
结果:
我们发现,我们执行重写后的方法不再是父类的了
super的使用
当我们在子类中重写了父类的方法,但是还想调用父类怎么办?
此刻我们就可以在子类中使用super()来调用父类的方法
案例:
# - 在子类中调用父类同名方法可以使用super()进行调用
# - 此处并不是只能从父类中调用,如果父类中不存在,也可以去父类的父类中查询
class Person(object):
def __init__(self,name,age):
self.name = name
self.age = age
def run(self):
print('我跑了100米')
class Father(Person):
def run(self):
print('我跑了105米')
class Son(Father):
# 我们一般情况下,重写父类的init方法,都是为了扩展功能
# 使用的方式:(减少代码的重复)
def __init__(self,name,age,id):
super().__init__(name,age) # 默认就是上述写法
self.id = id
def run(self):
# 如果我们想要在此处调用person中的run需要怎么做?
# 如果在super中什么也不写,默认就是优先从Son的父类中查询
# super(Son, self).run()
# 如果我们想让其从Father的父类中查询,需要怎么做?? 将Son 替换为Father
# 此时就可以获取Person类中的drive方法中的内容
# super(Father, self).run()
# 同时,我们也可以直接通过类名进行调用
# super(Son, self).run() #不推荐
Person.run(self) #推荐这种 见名之意
print('儿子和父亲差了10米')
结果:
多态
就是执行了相同的代码,但是体现了不同的结果,例如,一个狗和猫,都有吃的功能,但是呢,狗爱吃骨头,猫爱吃鱼,这就是多态,
但是,在python中多态因为不能定义类型,所以不能父类引用指向子类对象,就显得多态不重要了,了解即可。
案例:
# 创建动物类
class Animal(object):
def eat(self):
print('喜欢吃饭')
# 创建狗类
class Dog(Animal):
def eat(self):
print('爱吃骨头')
# 创建猫类
class Cat(Animal):
def eat(self):
print('爱吃鱼')
# 创建func方法
# 这个方法用来调用eat这个方法
# obj是每一个对象
def func(obj):
obj.eat()
if __name__ == '__main__':
# 创建对象
a = Animal()
d = Dog()
c = Cat()
# 开始体现多态
# 我们发现虽然调用了同一个方法
# 但是呢,所展现的状态不一样
# 这就是所谓的多态
func(a)
func(d)
func(c)
结果: