我们可以将 Python类中的方法分为三个不同的类别,即类方法、实例方法和静态方法。
Python 类方法是绑定到类而不是类的实例的方法。它可以在类本身上调用,而不是在类的实例上调用。
注意,不要将类方法与静态方法混淆:虽然两者都是通过类来调用的,但静态方法无法访问 “cls
” 参数,因此它不能修改类的状态。
与类方法不同,实例方法可以访问对象的实例变量。它也可以访问类变量,因为类变量是对所有对象都相同的。
在Python中创建类方法有两种途径:
classmethod()
函数@classmethod
装饰器Python 有一个内置函数 classmethod()
,它可以将一个实例方法转换为类方法,从而可以仅使用类引用来调用,而不需要对象。
语法:
classmethod(实例方法)
在Person类中,定义一个带有self
参数(指向调用对象的引用)的show_count()
实例方法。它打印count
的值。接下来,将该方法转换为类方法total_count()
,以便可以通过类引用来访问。
class Person():
count = 0
def __init__(self, name, age):
self.name = name
self.age = age
Person.count += 1
def show_count(self):
print(f'总人数是:{Person.count}')
total_count = classmethod(show_count)
person1 = Person('张三', 20)
person2 = Person('李四', 22)
person1.show_count()
person2.show_count()
Person.total_count()
输出:
总人数是:2
总人数是:2
总人数是:2
@classmethod
装饰器创建类方法使用@classmethod()
装饰器是定义类方法的推荐方式,因为它比先声明一个实例方法然后将其转换为类方法更方便。
类方法将类作为隐式的第一个参数接收,就像实例方法接收实例一样。要声明一个类方法,请使用这种惯用法:
class C:
@classmethod
def f(cls, arg1, arg2):
# 方法体
类方法既可以在类上调用(例如 C.f()
),也可以在实例上调用(例如 C().f()
)。
类方法不同于C++或Java中的静态方法。
class Person():
count = 0
def __init__(self, name, age):
self.name = name
self.age = age
Person.count += 1
@classmethod
def show_count(cls):
print(f'总人数是:{cls.count}')
@classmethod
def create_person(cls, name, age):
return cls(name, age)
p1 = Person('张三', 20)
p2 = Person('李四', 22)
p3 = Person('王五', 21)
p4 = Person.create_person('马六', 23)
Person.show_count()
输出:
总人数是:4
类属性是属于类的那些变量,其值在该类的所有实例之间共享。
要在类方法中访问类属性,请使用 cls
参数,后跟点(.
)符号和属性名。
class Person():
name = '张三'
@classmethod
def show_name(cls):
return cls.name
print(Person.show_name())
输出:
张三
Python 的 setattr()
函数用于动态地设置属性。如果你想向一个类添加类方法,将方法名作为参数值传递给 setattr()
函数。
class Person():
pass
# 类方法
@classmethod
def say_hello(cls):
print('hello world')
# 动态添加
setattr(Person, 'my_say_hello', say_hello)
obj = Person
obj.my_say_hello()
输出:
hello world
Python 的 del
运算符用于动态地删除类方法。如果你试图访问已删除的方法,代码将会引发 AttributeError
。
class Person():
# 类方法
@classmethod
def say_hello(cls):
print('hello world')
# 此时可以正常访问类方法
Person.say_hello()
# 动态删除类方法
del Person.say_hello
# 此时访问类方法会报异常
Person.say_hello()