Python快速入门(九)面向对象2:继承、多态、静态方法、单例等
前言:主要介绍继承、多态、静态方法、new方法、单例等。
1.单继承
- 继承:实现代码的重用,相同的代码不需要重复的编写
- 子类拥有父类的所有方法和属性
- 子类 继承自 父类,可以直接 享受 父类中已经封装好的方法,不需要再次开发
- 子类 中应该根据 职责,封装 子类特有的 属性和方法
代码:
class Animal:
def eat(self):
print("吃")
def drink(self):
print("喝")
def run(self):
print("跑")
def sleep(self):
print("睡")
class Dog(Animal):
def bark(self):
print("汪汪叫")
class Cat(Animal):
def bark(self):
print("喵喵喵")
# 创建一个对象 - 狗对象
wang = Dog()
wang.eat()
wang.drink()
wang.run()
wang.sleep()
wang.bark()
print("*"*100)
tom = Cat()
tom.eat()
tom.drink()
tom.run()
tom.sleep()
tom.bark()
输出:
2.继承的传递性
- C 类从 B 类继承,B 类又从 A 类继承,那么 C 类就具有 B 类和 A 类的所有属性和方法。
- 子类 拥有 父类 以及 父类的父类 中封装的所有 属性 和 方法。
代码:
class Animal:
def eat(self):
print("吃")
def drink(self):
print("喝")
def run(self):
print("跑")
def sleep(self):
print("睡")
class Dog(Animal):
def bark(self):
print("狗特有的属性:汪汪叫")
class XiaoTianQuan(Dog):
def fly(self):
print("哮天犬特有的属性:我会飞")
# 创建一个哮天犬的对象
xtq = XiaoTianQuan()
xtq.eat()
xtq.drink()
xtq.run()
xtq.sleep()
xtq.bark()
xtq.fly()
输出:
- 注意:如果新建一个cat类继承animal类,添加cat的特有方法,则此时的xiaotianquan对象则不能调用cat里面的方法。
代码:
class Animal:
def eat(self):
print("吃---")
def drink(self):
print("喝---")
def run(self):
print("跑---")
def sleep(self):
print("睡---")
class Dog(Animal):
def bark(self):
print("汪汪叫")
class XiaoTianQuan(Dog):
def fly(self):
print("我会飞")
class Cat(Animal):
def catch(self):
print("抓老鼠")
# 创建一个哮天犬的对象
xtq = XiaoTianQuan()
xtq.fly()
xtq.bark()
xtq.eat()
xtq.catch() #出错
输出:
3.覆盖父类方法
- 如果子类中,重写了父类的方法,在使用子类对象调用方法时,会调用子类中重写的方法。
代码:
class Animal:
def eat(self):
print("吃---")
def drink(self):
print("喝---")
def run(self):
print("跑---")
def sleep(self):
print("睡---")
class Dog(Animal):
def bark(self):
print("汪汪叫")
class XiaoTianQuan(Dog):
def fly(self):
print("我会飞")
def bark(self):
print("叫得跟神一样...")
xtq = XiaoTianQuan()
xtq.bark()
输出:
4.拓展父类方法
- 可以重写父类的方法
- 使用 super(). 调用原本在父类中封装的方法
- 父类名.方法(self)
代码:
class Animal:
def eat(self):
print("吃---")
def drink(self):
print("喝---")
def run(self):
print("跑---")
def sleep(self):
print("睡---")
class Dog(Animal):
def bark(self):
print("汪汪叫")
class XiaoTianQuan(Dog):
def fly(self):
print("我会飞")
def bark(self):
# 针对子类特有的需求,编写代码
print("啦啦啦...")
# 使用 super(). 调用原本在父类中封装的方法
# super().bark()
# 父类名.方法(self)
Dog.bark(self)
# 增加其他子类的代码
print("xxxx")
xtq = XiaoTianQuan()
xtq.bark()
5.父类的私有属性和私有方法
- 子类不能继承父类的私有属性和私有方法。
代码:
class A:
def __init__(self):
self.num1 = 12
self.__num2 = 15
def __test(self):
print("私有方法 %d %d" % (self.num1, self.__num2))
class B(A):
def demo(self):
# 在子类的对象方法中,不能访问父类的私有属性
# print("访问父类的私有属性 %d" % self.__num2)
# 在子类的对象方法中,不能调用父类的私有方法
# self.__test()
pass
# 创建一个子类对象
b = B()
print(b)
b.demo()
6.父类的公有方法
如果需要访问父类的私有方法,可以通过父类的共有方法,访问这个父类的私有方法,我们可以在共有方法里面设置一些条件才能访问私有方法,这样会更加安全。
代码:
class A:
def __init__(self):
self.num1 = 100
self.__num2 = 200
def __test(self):
print("私有方法 %d %d" % (self.num1, self.__num2))
def test(self):
print("父类的公有方法 %d" % self.__num2)
self.__test()
class B(A):
def demo(self):
# 访问父类的公有属性
print("子类方法 %d" % self.num1)
# 调用父类的公有方法
self.test()
pass
# 创建一个子类对象
b = B()
print(b)
b.demo()
# 在外界访问父类的公有属性/调用公有方法
print(b.num1)
b.test()
输出:
7.多继承&注意事项
- 子类 可以拥有 多个父类,并且具有 所有父类 的 属性 和 方法
- 例如:孩子 会继承自己 父亲 和 母亲 的 特性
- 注意:Java是单继承
代码:
class A:
def test(self):
print("test 方法")
class B:
def demo(self):
print("demo 方法")
class C(A, B):
"""多继承可以让子类对象,同时具有多个父类的属性和方法"""
pass
# 创建子类对象
c = C()
c.test()
c.demo()
输出:
注意事项代码:
class A:
def test(self):
print("A --- test 方法")
def demo(self):
print("A --- demo 方法")
class B:
def test(self):
print("B --- test 方法")
def demo(self):
print("B --- demo 方法")
class C(B, A):
"""多继承可以让子类对象,同时具有多个父类的属性和方法"""
pass
# 创建子类对象
c = C()
c.test()
c.demo()
# 确定C类对象调用方法的顺序
print(C.__mro__)
输出:
8.多态
- 多态 不同的 子类对象 调用相同的 父类方法,产生不同的执行结果。
- 多态 可以 增加代码的灵活度
- 以 继承 和 重写父类方法 为前提
- 是调用方法的技巧,不会影响到类的内部设计
代码:
class Dog(object):
def __init__(self, name):
self.name = name
def game(self):
print("%s 蹦蹦跳跳的玩耍" % self.name)
class XiaoTianDog(Dog):
def game(self):
print("%s 飞到天上去玩耍" % self.name)
class Person(object):
def __init__(self, name):
self.name = name
def game_with_dog(self, dog):
print("%s 和 %s 快乐的玩耍" % (self.name, dog.name))
# 让狗玩耍
dog.game()
# 创建一个狗对象
wangcai = XiaoTianDog("飞天旺财")
# 创建一个小明对象
xiaoming = Person("小明")
# 让小明调用和狗玩的方法
xiaoming.game_with_dog(wangcai)
输出:
9.类属性和实例属性
- 类属性 就是给 类对象 中定义的 属性
- 通常用来记录 与这个类相关 的特征
- 类属性 不会用于记录 具体对象的特征
代码:
class Tool(object):
# 使用赋值语句定义类属性,记录所有工具对象的数量
count = 0
def __init__(self, name):
self.name = name
print(name)
# 让类属性的值+1
Tool.count += 1
# 1. 创建工具对象
tool1 = Tool("斧头")
tool2 = Tool("榔头")
tool3 = Tool("水桶")
# 2. 输出工具对象的总数
print(Tool.count)
输出:
10.类方法
- 类属性 就是针对 类对象 定义的属性
- 类方法 就是针对 类对象 定义的方法
代码:
class Tool(object):
# 使用赋值语句定义类属性,记录所有工具对象的数量
count = 0
@classmethod
def show_tool_count(cls):
print("工具对象的数量 %d" % cls.count)
def __init__(self, name):
self.name = name
# 让类属性的值+1
Tool.count += 1
# 创建工具对象
tool1 = Tool("斧头")
tool2 = Tool("榔头")
# 调用类方法
Tool.show_tool_count()
输出:
11.静态方法
- 通过类名.调用静态方法 - 不需要创建对象
代码:
class Dog(object):
@staticmethod
def run():
# 不访问实例属性/类属性
print("小狗要跑...")
Dog.run()
输出:
12.方法案列综合
代码:
class Game(object):
# 历史最高分
top_score = 0
def __init__(self, player_name):
self.player_name = player_name
@staticmethod
def show_help():
print("帮助信息:让僵尸进入大门")
@classmethod
def show_top_score(cls):
print("历史记录 %d" % cls.top_score)
def start_game(self):
print("%s 开始游戏啦..." % self.player_name)
# 查看游戏的帮助信息
Game.show_help()
# 查看历史最高分
Game.show_top_score()
# 创建游戏对象
game = Game("小明")
game.start_game()
输出:
13.new方法
代码:
class MusicPlayer(object):
def __new__(cls, *args, **kwargs):
# 创建对象时,new方法会被自动调用
print("创建对象,分配空间")
# 为对象分配空间
instance = super().__new__(cls)
# 返回对象的引用
return instance
def __init__(self):
print("播放器初始化")
# 创建播放器对象
player = MusicPlayer()
print(player)
输出:
14.Python单例
- 目的:让 类 创建的对象,在系统中 只有 唯一的一个实例
- 每一次执行 类名() 返回的对象,内存地址是相同的
代码:
class MusicPlayer(object):
# 记录第一个被创建对象的引用
instance = None
# 记录是否执行过初始化动作
init_flag = False
def __new__(cls, *args, **kwargs):
# 1. 判断类属性是否是空对象
if cls.instance is None:
# 2. 调用父类的方法,为第一个对象分配空间
cls.instance = super().__new__(cls)
# 3. 返回类属性保存的对象引用
return cls.instance
def __init__(self):
# 1. 判断是否执行过初始化动作
if MusicPlayer.init_flag:
return
# 2. 如果没有执行过,在执行初始化动作
print("初始化播放器")
# 3. 修改类属性的标记
MusicPlayer.init_flag = True
# 创建多个对象
player1 = MusicPlayer()
print(player1)
player2 = MusicPlayer()
print(player2)
输出:
结束!!!