一、内置装饰器
内置装饰器 | 含义 |
---|---|
classmethod | 类方法 |
staticmethod | 静态方法 |
二、普通方法(回顾)
-
定义:
-
第一个参数为self,代表 实例本身
-
-
调用:
-
要有实例化的过程,通过 实例对象.方法名 调用
-
# 1. 定义类
class MethodsDemo:
param_a = 0 # 类变量
def normal_demo(self): # 定义一个类方法,第一个参数必须为self
"""
普通方法
:return:
"""
print("这是一个普通方法", self.param_a)
# 2. 调用
md = MethodsDemo()
md.normal_demo()
三、类方法
-
定义:
-
使用 @classmethod 装饰器,第一个参数为类本身,所以通常使用cls命名做区分(非强制)
-
在类内可以直接使用类方法或类变量,无法直接使用实例变量或方法
-
-
调用:
-
无需实例化,直接通过 类.方法名 调用,也可以通过 实例.方法名 调用
-
# 1. 类的定义
class MethodClass:
class_param = 0 # 类变量
def __init__(self): # 实列变量
self.a = 'abc'
def demo_method(self):
print('这是一个普通方法')
def demo_method2(self):
self.demo_method()
self.a = 'acb'
print('这是一个普通方法')
# 定义类方法必须加 classmethod装饰器
@classmethod
def class_method(cls): # 类方法,第一个参数需要改为cls
# cls.demo_method() 类方法内,不可以直接调用实列方法
# cls.a 类方法内,不可以直接调用实列变量
cls.class_method2() # 类方法内,可以直接调用类变量与类方法
print('这是一个类方法', cls.class_param) # 类变量是可以直接调用的
@classmethod
def class_method2(cls): # 类方法,第一个参数需要改为cls
print('这是一个类方法2', cls.class_param)
# 调用类方法
MethodClass.class_method() # 无需实例化,直接通过 类.方法名 调用,也可以通过 实例.方法名 调用
# 实例化调用
demo = MethodClass()
demo.demo_method() # 在调用过程中,类和实列都可以直接调用类方法
# 调用普通方法,需要实例化,要不然会报错
# MethodClass.demo_method()
三、静态方法
-
定义:
-
使用 @staticmethod 装饰器,没有和类本身有关的参数
-
无法直接使用任何类变量、类方法或者实例方法、实例变量
-
-
调用:
-
无需实例化,直接通过 类.方法名 调用,也可以通过 实例.方法名 调用
-
# 1. 定义
class MethodsDemo:
param_a = 0 # 定义类变量
def demo_method(self): # 普通方法
print('这是一个普通方法')
@classmethod
def class_method2(cls): # 类方法,第一个参数需要改为cls
print('这是一个类方法2')
@staticmethod # 定义静态方法 必须加@staticmethod装饰器
def static_demo(p):
"""
静态方法
:return:
"""
# self./cls. 不可以使用,没有这个参数
print("静态方法", p) # 无法直接调用类变量
# 2. 类调用
MethodsDemo.static_demo(5)
# 实列对象调用
demo = MethodsDemo()
demo.static_demo(5)
四、普通方法、类方法、静态方法的区别
名称 | 定义 | 调用 | 关键字 | 使用场景 |
---|---|---|---|---|
普通方法 | 至少需要一个参数self | 实例名.方法名() | 无 | 方法内部涉及到实例对象属性的操作 |
类方法 | 至少需要一个cls参数 | 类名.方法名() 或者实例名.方法名() | @classmethod | 如果需要对类属性,即静态变量进行限制性操作 |
静态方法 | 无默认参数 | 类名.方法名() 或者实例名.方法名() | @staticmethod | 无需类或实例参与 |
五、类方法实际案例
1、下面的代码实现的需求是格式化输出时间如果现在需求变更,输入 年、月、日 没法保证格式统一,可能是json,可能是其他格式的字符串,在不修改构造函数的前提下,如何更改代码?
class DateFormat:
def __init__(self, year=0, month=0, day=0):
self.year = year
self.month = month
self.day = day
def out_date(self):
return f"输入的时间为{self.year}年,{self.month}月,{self.day}日"
year, month, day = 2017, 7, 1
demo = DateFormat(year, month, day)
print(demo.out_date())
class DateFormat:
def __init__(self, year=0, month=0, day=0):
self.year = year
self.month = month
self.day = day
def out_date(self):
return f"输入的时间为{self.year}年,{self.month}月,{self.day}日"
@classmethod
def json_formate(cls, json_date):
"""
输入一个字典格式的数据类型,返回(2021,12,17)
"""
year, month, day = json_date['year'], json_date['month'], json_date['day']
return cls(year, month, day)
json_data = {'year': 2021, 'month': 12, 'day': 17}
# 使用json格式化,生成想要的日期格式,返回DateFormat实列
demo =DateFormat.json_formate(json_data)
print(demo.out_date())
六、静态方法实际案例
-
此方法没有任何和实例、类相关的部分,可以作为一个独立函数使用
-
某些场景下,从业务逻辑来说又属于类的一部分
"""
多轮比赛,每轮由不同的英雄对打
"""
class Game:
def __init__(self, first_hero, second_hero):
self.first_hero = first_hero
self.second_hero = second_hero
# fight 有和实列变量交互的部分,所有需要定义为一个普通方法
def fight(self):
print(f'本轮比赛开始,由{self.first_hero}vs{self.second_hero}')
# start 没有和类或实列交互的部分,那么就可以使用@staticmethod
@staticmethod
def start():
print('游戏开始')
Game.start()
game1 = Game("Bob", "Jack")
game2 = Game('Tom', 'Alice')
game1.fight()
game2.fight()