[python] python静态方法,类方法,实例方法实现及其区别
一 函数定义
- 格式
'def 函数名()
函数体
def myPyFirstFunc():print("hello python")
myPyFirstFunc()
-
带返回值的函数:返回函数调用的结果
def pythonReturnTest():return (1,2)
print(pythonReturnTest()[1])
-
带参数的函数:#定义一个加法函数
def 函数名(形参a,形参b)
函数体
def add(a,b):return a + b
print(add(1,2))
print(add(1,4))
二 静态方法
- 格式: 使用 @staticmethmod 装饰器修饰
-
应用: 某个方法既不需要使用实例属性也不需要使用类属性时,就可以考虑使用静态方法
-
注意: 静态方法与类无关,可以被转换成函数使用,属于类本身
2.1 经典示例
创建一个与日期相关的辅助函数,这些函数不需要访问或修改类的状态,因此适合作为静态方法
class DateUtils:@staticmethoddef is_weekday(date = datetime.now()):# 判断给定的日期是否为工作日return date.weekday() < 5@staticmethoddef next_weekday(date):#返回下一个工作日的日期next_day = date + timedelta(days = 1)while next_day.weekday() >= 5: #如果是周六或者周日,则继续加一天直到工作日next_day = next_day + timedelta(days = 1)return next_day
调用:
import datetimetoday = datetime.datetime(year=2025, month=5, day=13) # 假设今天是2025年5月13日,星期二
print(DateUtils.is_weekday(today)) # 输出: True,因为今天是周二,属于工作日next_workday = DateUtils.next_weekday(today) # 计算下一个工作日
print(next_workday.strftime("%Y-%m-%d")) # 输出下一个工作日的日期
2.2 特殊之处
- 对于python这门语言,类的静态方法就相当于一个普通函数,可以直接调用,也可以使用创建的实例的对象调用
date1 = DateUtils()
print(date1.next_weekday(today))
三 类方法
- 格式: 使用 @staticmethmod 装饰器修饰
- ,对于类方法,第一个参数必须是类对象自己,一般是以cls作为第一个参数
- 值得注意的是它可以传入其他类方法,并且可以访问类属性
# class 类名:
# @classmethod
# def 方法名(cls,形参):
# 方法体
- 当方法中需要使用到类对象(如访问私有类属性时)
- 类方法一搬是配合类属性使用
3.1 使用场景
当需要在所有实例之间共享某些数据时,可以使用类属性
计数器: 用于跟踪类被创建了多少个实例出来
四 实例方法
- 格式:不需要装饰器修饰符,但是第一个参数必须传递实例自己(self)
- 第一个参数必须是 self
- 表示调用该方法的实例本身
- Python 会自动传入这个参数,不需要手动传递
class 类名:
def 方法名(self, 其他参数):
方法体
五 详细区别
特性 | 实例方法 | 类方法 (@classmethod) | 静态方法 (@staticmethod) |
---|---|---|---|
第一个参数 | self(实例) | cls(类 ) | 无隐式参数 |
是否自动传参 | ✅ 是 | ✅ 是 | ❌ 否 |
可否访问实例属性 | ✅ 可以 | ❌ 不可以 | ❌ 不可以 |
可否访问类属性 | ✅ 可以 | ✅ 可以 | ❌ 不可以 |
可否修改实例状态 | ✅ 可以 | ❌ 不可以 | ❌ 不可以 |
可否修改类状态 | ✅ 可以 | ✅ 可以 | ❌ 不可以 |
调用方式 | 必须通过实例(或显式传实例) | 类或实例均可 | 类或实例均可 |
主要用途 | 操作实例数据(如初始化、修改状态等) | 操作类数据(如工厂方法、类级别的操作) | 执行与类/实例有关的逻辑,但不依赖类或实例 |
- 首先我们要明确下面这个例子,name = "python"是什么属性--->类属性,他并非实例属性。而@classmethod也是类方法,调用类方法后可以修改/获取类属性。类方法中必须传递cls也就是类本身。
- 接下来看看实例属性和实例方法
- 下面定义了一个get_name(self,name)实例方法,这个函数第一次被调用时,实例属性还没有被创建,就会去找类中有没有这个属性,找到之后返回了类属性中的这个值。
- 当调用set_name(self,name)实例方法后,实例属性self.name被创建,此时如果调用get_name()获取到的实例属性和调用getname获取到的类属性的值就不再相同。
- 值得注意的是,实例属性一般是在__init__第一次构造时被创建,或者某些实例方法中被创建。
- 而类属性在类被定义的时候就已经存在了。
class PObject(object):name = "python"@classmethoddef setname(cls,name):cls.name = name@classmethoddef getname(cls):return cls.namedef get_name(self):return self.namedef set_name(self,name):self.name = namePObject.setname("C++")
print(PObject.getname())p1 = PObject()
print(p1.getname())
p1.setname("Java")
p1.set_name("VUE")
print(PObject.getname())
print(p1.get_name())
5.1 如何区分实例属性和类属性
简单来说定义在类里面,方法外面的都属于类属性,在方法内部通过self访问的都是实例属性.
5.2 一些奇怪的操作
静态方法内调用实例属性
- 静态方法: :内部不要去尝试访问实例属性和类属性,虽然可以通过一些骚操作实现
首先静态方法不接受隐式的第一个参数,cls或者self,这意味着它们不能访问实例或类的状态。它们通常用于与类相关,但不需要访问类或其实例属性的功能。
但是却可以手动类和实例
- 对于这种写法其实就相当于是一个函数的功能了,完全可以单独写成一个外部函数。
- 因为这种写法的设计无非是传入一个类的去操作或者获取这个类,本身就有了类方法,就应该使用类方法去获取和操作这个类的属性。
class PObject(object):name = "python"@staticmethoddef isstaticfunction(cls,self):print(f"传递了这个类{cls}和这个实例对象{self}")p1 = PObject()PObject.isstaticfunction(PObject,p1)