类的结构
实例
-
使用面向对象开发,第 1 步 是设计 类
-
使用 类名() 创建对象,创建对象 的动作有两步:
-
在内存中为对象 分配空间
-
调用初始化方法
__init__
为 对象初始化 -
对象创建后,内存 中就有了一个对象的实实在在的存在 —— 实例
每一个对象都有自己 独立的内存空间,保存各自不同的属性
多个对象的方法,在内存中只有一份,在调用方法时,需要把对象的引用传递到方法内部
__init__定义实例属性
实例方法(self)
调用实例方法 对象名.方法名()
类是一个特殊的对象
-
在程序运行时,类同样会被加载到内存
-
在
Python
中,类是一个特殊的对象 —— 类对象 -
在程序运行时,类对象在内存中 只有一份,使用 一个类可以创建出很多个对象实例
-
除了封装实例的属性和方法外,类对象还可以拥有自己的属性和方法
-
类属性
-
类方法
-
通过
类名.
的方式可以访问类的属性或者调用类的方法
类方法(cls)
调用类属性: 类名.属性
调用类方法:类名.方法名()
类的属性和实例属性
概念和使用
- 类属性就是给类对象中定义的属性
- 通常用来记录与这个类相关的特征
- 类属性不会用于记录具体对象的特征
案例:
- 定义一个工具类
- 每件工具都有自己的
name
- 需求 —— 知道使用这个类,创建了多少个工具对象
分析:
- 定义实例属性 name
- 定义类属性,记录创建工具对象的总数
class Tool(object):
# 使用赋值语句,定义类属性,记录创建工具对象的总数
count = 0
def __init__(self, name):
self.name = name
# 针对类属性做一个计数+1
Tool.count += 1
# 创建工具对象
tool1 = Tool("斧头")
tool2 = Tool("榔头")
tool3 = Tool("铁锹")
# 知道使用 Tool 类到底创建了多少个对象?
print("现在创建了 %d 个工具" % Tool.count) #工具对象的数量 3
属性的获取机制
在 Python
中属性的获取存在一个向上查找机制
- 首先在对象内部查找对象属性
- 没有找到就会向上寻找类属性
因此,要访问类属性有两种方式:
- 类名.类属性
- 对象.类属性 (不推荐)
class Tool(object):
#使用赋值语句定义类属性,记录所有工具对象的数量
count=0
def __init__(self,name):
self.name=name
#每调用一次类定义的初始化值一次,让类属性的值+1
Tool.count+=1
#1.创建工具对象
tool1=Tool('斧头')
tool2=Tool('榔头')
tool3=Tool('水桶')
#2.输出工具对象的总数
#print(Tool.count)
print('工具对象总数 %d'%tool1.count) #工具对象总数 3
print('===> %d'%Tool.count) #===> 3
注意:如果使用 对象.类属性 = 值
赋值语句,只会给对象添加一个属性,而不会影响到类属性的值
class Tool(object):
#使用赋值语句定义类属性,记录所有工具对象的数量
count=0
def __init__(self,name):
self.name=name
#每调用一次类定义的初始化值一次,让类属性的值+1
Tool.count+=1
#1.创建工具对象
tool1=Tool('斧头')
tool2=Tool('榔头')
tool3=Tool('水桶')
#2.输出工具对象的总数
#print(Tool.count)
tool1.count=99
print('工具对象总数 %d'%tool1.count) #工具对象总数 99
print('===> %d'%Tool.count) #===> 3
类方法和静态方法
类方法
类方法就是针对类对象定义的方法
在类方法内部可以直接访问类属性或者调用其他的类方法
语法如下
@classmethod
def 类方法名(cls):
pass
通过 类名.
调用类方法,调用方法时,不需要传递 cls
参数
在方法内部
- 可以通过
cls.
访问类的属性 - 也可以通过
cls.
调用其他的类方法
案例:
- 定义一个工具类
- 每件工具都有自己的
name
- 需求 —— 在类封装一个
show_tool_count
的类方法,输出使用当前这个类,创建的对象个数
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('榔头')
tool3=Tool('水桶')
# 调用类方法
Tool.show_tool_count() #工具对象的数量 3
静态方法
在开发时,如果需要在类中封装一个方法,这个方法:
- 既不需要访问实例属性或者调用实例方法
- 也不需要访问类属性或者调用类方法
这个时候,可以把这个方法封装成一个静态方法
语法:
@staticmethod
def 静态方法名():
pass
通过 类名.
调用静态方法
class Dog(object):
@staticmethod
def run():
#不访问实例属性/类属性
print('小狗要跑...')
#通过类名.调用静态方法 - 不需要创建对象
Dog.run() #小狗要跑...
方法综合案例
需求:
- 设计一个
Game
类 - 属性
- 定义一个类属性
top_score
记录游戏的历史最高分 - 定义一个实例属性
player_name
记录当前游戏的玩家姓名
- 方法
- 静态方法
show_help
显示游戏帮助信息 - 类方法
show_top_score
显示历史最高分 - 实例方法
start_game
开始当前玩家的游戏
- 主程序步骤
- 查看帮助信息
- 查看历史最高分
- 创建游戏对象,开始游戏
class Game(object):
#定义类属性:历史最高分
top_scoer=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_scoer)
#定义实例方法
def start_game(self):
print('%s 开始游戏啦...'% self.player_name)
#查看游戏的帮助信息
Game.show_help()
#查看历史最高分
Game.show_top_score()
#创建游戏对象
game=Game('小明')
game.start_game()
运行结果
帮助信息:让僵尸进入大门
历史记录0
小明 开始游戏啦...
小结
- 实例方法 —— 方法内部需要访问实例属性
- 实例方法内部可以使用
类名.
访问类属性
- 类方法 —— 方法内部只需要访问类属性
- 静态方法 —— 方法内部,不需要访问实例属性和类属性
- 如果方法内部即需要访问实例属性,又需要访问类属性,应该定义实例方法
- 因为,类只有一个,在实例方法内部可以使用
类名.
访问类属性
- 因为,类只有一个,在实例方法内部可以使用