Python多态与类属性、类方法

学习地址

多态

不同的子类调用相同的父类方法,产生不同的执行结果,以继承和重写父类方法为前提

案例演练

需求:

  1. Dog类中封装方法game
    • 普通狗只是简单的玩耍
  2. 定义XiaoTianDog继承自Dog,并且重写game方法
    • 小天犬可以在天上玩耍
  3. 定义Person类,并且封装一个和狗玩的方法
    • 在方法内部,直接让狗对象调用game方法
实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
 class Dog:
def __init__(self,name):
self.name=name
def game(self):
print('playing on the ground')

class XiaoTianDog(Dog):
def game(self):
print('%s playing in the sky' %self.name)

class Person:
def __init__(self,name):
self.name=name
def play_with_dog(self,dog):
print('%s play with %s' %(self.name,dog.name))
dog.game()

# 1. 创建狗对象
# wangcai=Dog('wangcai')
wangcai=XiaoTianDog('wangcai')
# 2. 创建小明对象
xiaoming=Person('小明')
# 3. 让小明调用和狗玩的方法
xiaoming.play_with_dog(wangcai)

类属性与实例属性

类的结构
  1. 实例
    • 使用面向对象开发时,第一步时设计类
    • 使用类名()创建对象,创建对象的动作分两步:分配内存; __init__(self)初始化
    • 创建完成,内存中就有了一个对象,实实在在的存在 - 实例
类是一个特殊的对象

Python中一切皆对象

  • class AAA:定义的类属于类对象
  • object=AAA()属于实例对象

程序运行时,类对象在内存中只有一份,使用一个类可以创建出很多个对象实例
除了封装实例的属性和方法外,类对象还可以拥有自己的属性和方法
通过类名.的方式可以访问类的属性调用类的方法

概念

类属性就是给类对象中定义的属性
通常用来记录与这个类相关的特征
类属性不会用于记录具体对象的特征

示例需求:

  1. 定义一个工具类
  2. 每个工具类都有自己的name
  3. 需求 - - 知道这个类,创建了多少个工具对象
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    class Tool(object):
    # 使用赋值语句定义类属性
    count=0
    def __init__(self,name):
    self.name=name
    # 使用类名访问类属性
    Tool.count+=1

    # 1. 创建工具对象
    too1=Tool('斧头')
    too2=Tool('锤子')
    # 2. 输出工具对象的数量
    print(Tool.count)

    - - - - - - -
    2
属性的向上查找机制

Python中属性的获取存在一个向上查找机制
即,访问对象属性时首先在指定的对象内部查找,没有找到则向上寻找类的属性,这就是继承可以实现代码重用。
那么 ,访问对象属性有两种方法

  1. 类名.类属性
  2. 对象名.类属性(不推荐)
使用对象名+类属性进行赋值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Tool(object):
# 使用赋值语句定义类属性
count=0
def __init__(self,name):
self.name=name
# 使用类名访问类属性
Tool.count+=1

# 1. 创建工具对象
too1=Tool('斧头')
too2=Tool('锤子')
too1.count+=1 # 这条赋值语句并不是访问类属性,而是给对象添加属性
# 2. 输出工具对象的数量
print(Tool.count)

- - - - - - -
2

使用对象.类属性=值赋值语句只会给实例对象添加一个属性,而不会影响到类属性的值。

类方法和静态方法

  1. 类属性就是针对类对象定义的属性
    • 使用赋值语句在class关键字下方可以定义类属性
    • 类属性用于记录与这个类相关的特征
  2. 类方法就是针对类对象定义的方法

    • 在类方法内部可以直接调用类属性或者带哦用其他的类方法
  3. 语法

    1
    2
    3
    @classmethod
    def function_name(cls):
    pass
    • 类方法需要用修饰器classmethod来标识,告诉解释器这是一个类方法
    • 类方法的第一个参数应该是cls,由哪一个类调用的方法,方法内的cls就是那一个类的引用,和实例方法的第一个参数self类似
    • 通过类名.调用类方法,调用方法时,不需要传递cls参数
    • 在方法内部,可以通过cls.访问类的属性,也可以通过cls.调用其他的类方法
示例需求
  1. 定义一个工具类
  2. 每个工具都有自己的name
  3. 需求–在类封装一个show_tool_count的类方法,输出使用当前类所创建的实例对象的数量
实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Tool(object):
count=0
@classmethod
def show_tool_count(cls):
print('the number of tools is %d' %cls.count)
def __init__(self,name):
self.name=name
Tool.count+=1

too1=Tool('锤子')
too2=Tool('斧头')
Tool.show_tool_count()

- - - - - - - - - - - -
the number of tools is 2

静态方法

在开发时,如果需要在类中封装一个方法,这个方法

  • 即不需要访问实例属性或者调用实例方法
  • 也不需要访问类属性或者调用类方法

那么,就可以把这个方法封装成一个静态方法

语法
1
2
3
@staticmethod
def function_name():
pass
  • 静态方法需要使用修饰器staticmethod来标识,告诉解释器这是一个静态方法
  • 通过类名.调用静态方法

综合演练

需求
  1. 设计一个Game
  2. 属性

    • 定义一个类属性top_score记录游戏的历史最高分
    • 定义一个实例属性player_game记录当前游戏的玩家姓名
  3. 方法

    • 静态方法show_help显示游戏帮助信息
    • 类方法show_top_score显示历史最高分
    • 实例方法start_game开始当前玩家的游戏
  4. 主程序步骤

    • 查看帮助信息
    • 查看历史最高分
    • 创建游戏对象,开始游戏
实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class Game(object):
# 类属性
top_score=0

def __init__(self,player_name):
self.name=player_name # 实例属性

# 静态方法,不需要访问其他信息
@staticmethod
def show_help():
print('---- help ---')

# 类方法,使用cls访问类属性
@classmethod
def show_top_score(cls):
print('The highest score is %d' %cls.top_score)

# 实例属性
def start_game(self):
print('1 2 3 , run')

Game.show_help()
Game.show_top_score()
player=Game('小明')
player.start_game()

- - - - - - - - - - - - - - -
---- help ---
The highest score is 0
1 2 3 , run
小结
  1. 实例方法:方法内部需要访问实例属性

    • 实例方法内部可以使用类名.访问类属性
  2. 类方法: 方法内部只需要访问类属性,使用cls.访问类属性

  3. 静态方法: 方法内部,不需要访问实例属性和类属性