本节介绍一些面向对象编程的其他知识
九、类属性和类方法,通过类调用属性和方法
一、区分类和实例
创建的对象叫类的实例,动作叫类的实例化。对象的属性和方法叫实例属性和实例方法
二、关注程序运行过程
1、对象拥有各自的实例属性]
2、通过self调用实例化方法
——访问自己属性
——调用自己方法
3、存储方式:
——每个对象只有一份独立的内存空间来保存自己的属性
——多个对象使用的实例化方法内存中只有一份,调用时只是把对象的引用传入方法(这就是self的意义)
三、类对象
1、类是一种特殊的对象,在内存中会调入并且只有一份
2、类可以有自己的属性和方法,比如想要访问创造了多少个实例
3、类方法和属性可以通过类名.的方法实现
四、类属性
1、类属性记录关于类的特征、而非实例化对象的特征
2、可以让每次实例化时访问一个类属性,如加一,访问类属性时可以知道这个类创造了多少个对象
五、类方法
1、类这个特殊对象访问类属性等的类方法
2、给一个方法加上@classmethod进行装饰,就是类方法
3、使用@classmethod修饰器,来告诉解释器这是一个类方法
4、类方法的第一个参数应该是cls,代表这个类,和对象方法第一个参数self相似,使用cls.类属性,可以在类方法内访问类属性
5、调用类方法时不需要传递其他参数
class Tool:
#类属性count,直观上很像类内的全局变量,在类调入内存时就有了,和是否实例化无关
count=0
def __init__(self, name):
self.name = name
# 针对类属性做一个计数+1
Tool.count += 1
#给一个方法加上classmethod进行装饰,就是类方法
@classmethod
def show_tool_count(cls):
"""显示工具对象的总数"""
print("类方法 工具对象的总数 %d" % cls.count)
# 创建工具对象
tool1 = Tool("斧头")
tool2 = Tool("榔头")
tool3 = Tool("铁锹")
# 知道使用 Tool 类到底创建了多少个对象?
print("现在创建了 %d 个工具" % Tool.count)
print("现在创建了 %d 个工具" % tool3.count) # 不规范的写法
tool3.count = 99 #创建了一个count对象属性
print("工具对象总数 %d" % tool3.count) #99
print("===> %d" % Tool.count)
Tool.show_tool_count()
现在创建了 3 个工具
现在创建了 3 个工具
工具对象总数 99
===> 3
类方法 工具对象的总数 3
静态方法
1、类中不需要访问类属性和实例属性的方法,如打印一些关于类的帮助
2、使用@staticmethod装饰器进行装饰,告诉解释器这是一个静态变量
class Dog(object):
@staticmethod
def run():
# 静态方法内不需要访问实例属性/类属性
print("小狗要跑...")
# 通过类名.调用静态方法 - 不需要创建对象
Dog.run()
小狗要跑...
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)
# 1. 查看游戏的帮助信息
Game.show_help()
# 2. 查看历史最高分
Game.show_top_score()
# 3. 创建游戏对象
game = Game("小明")
game.start_game()
object
帮助信息:让僵尸进入大门
历史记录 0
小明 开始游戏啦...
object
十、单例模式
1、设计模式
就是针对某些问题的成熟的解决方案,使代码可重用性、可靠性、可扩展性强
2、单例模式
1、目的:让类创建的对象,在系统中只有一个实例
2、执行类名返回地址,内存地址相同
3、应用场景:如手机声音播放器,一次性只能播放一首歌,只能有一个实例存在
3、__new__方法
工作流程
1、在内存中为对象分配空间。2、返回对象的引用。3、python获得来自对象的引用后,将引用作为第一个参数传递给__init__方法进行初始化
重写__new__方法的代码非常固定
return一个super().new(cls),否则不会调用引用也不会初始化
class MusicPlayer(object):
instance = None
@classmethod
def __new__(cls, *args, **kwargs):
if cls.instance is None:
# 1. 创建对象时,new方法会被自动调用
print("创建对象,分配空间")
# 2. 为对象分配空间
cls.instance = super().__new__(cls)
# 3. 返回对象的引用
# print('%x' % id(instance))
return cls.instance
def __init__(self, music_name):
print("播放器初始化")
self.music_name = music_name
# 创建播放器对象
player1 = MusicPlayer('周杰伦')
print(player1.music_name)
player2 = MusicPlayer('倩女幽魂')
print(player2.music_name)
# 单例模式是为了让player1 和player2是同一个对象
print(player1)
print(player2)
创建对象,分配空间
播放器初始化
周杰伦
播放器初始化
倩女幽魂
<main.MusicPlayer object at 0x7ffb38b669d0>
<main.MusicPlayer object at 0x7ffb38b669d0>