python类成员的理解

发布时间 2023-12-11 15:27:08作者: Albert1654

参考:https://www.cnblogs.com/code3/p/17222327.html

关于类中的 类函数、成员函数、静态函数、类变量、成员变量,做一下解释


1、类函数(Class Method):类函数是定义在类上的函数,可以访问类变量和类方法。它们的第一个参数通常被命名为cls,表示类本身。可以使用@classmethod装饰器来定义类函数。

示例代码:

class MyClass:
    count = 0 # 类变量
 
    @classmethod
    def increase_count(cls):
        cls.count += 1
 
print(MyClass.count) # 0
MyClass.increase_count()
print(MyClass.count) # 1

若不加@classmethod,调用函数会报错MyClass.increase_count() missing 1 required positional argument: 'cls'

我的理解是,用@classmethod声明类函数后,在调用函数时,python会自动将类的地址传入函数的第一个参数,即这里的cls

类函数即可以通过类去调用,也可以通过这个类的势力去调用

# 接上文
a = MyClass()
a.increase_count()
print(a.count)

2、成员函数(Instance Method)或者叫实例方法:成员函数是定义在类中的函数,需要通过类的实例来调用。它们的第一个参数通常被命名为`self`,表示调用该方法的实例本身。成员函数可以访问类变量和成员变量。在定义时,不需要添加任何装饰器。

示例代码:

class MyClass:
    class_string = "count加1" # 类变量
    def __init__(self):
        self.count = 0 # 成员变量
 
    def increase_count(self):
        self.count += 1
        print(self.class_string) # 访问类变量前要加self
 
my_object = MyClass()
print(my_object.count) # 0
my_object.increase_count()
print(my_object.count) # 1

成员函数一般通过实例去调用,python自动将实例的地址传入该函数的第一个参数,即这里的self

当然也可以通过类去调用成员函数,但是直接调用会报错MyClass.increase_count() missing 1 required positional argument: 'self'

因为调用的函数有一个self参数,即该实例地址。所以要显式传入实例

# 接上文
my_object = MyClass()
MyClass.increase_count() # 报错
MyClass.increase_count(my_object) # 显式传入实例才能正常调用

3、静态函数(Static Method):静态函数是定义在类中的函数,它们与类和实例都没有直接关系。静态函数不能访问类变量和成员变量。在定义时,需要使用`@staticmethod`装饰器来定义静态函数。

示例代码:

class MyClass:
    @staticmethod
    def say_hello():
        print("Hello, World!")
 
MyClass.say_hello() # 一般通过类去调用静态函数
my_object.say_hello() # 也可以通过实例去调用静态函数

我的理解是,用@staticmethod声明函数后,在调用静态函数时,python不会将类或实例的地址传入函数的第一个参数。因此说静态函数不能访问类变量和成员变量


4、类变量(Class Variable):类变量是定义在类上的变量,所有的类实例都可以访问它。类变量通常用于表示与类相关的状态或共享的数据。

示例代码:

class MyClass:
    count = 0 # 类变量,一般用于描述类的普遍特性

    @classmethod
    def class_method(cls):
        print(cls.count) # 类方法中用cls调用类变量
        
    def instance_method(self):
        print(self.count) # 实例方法中用self调用类变量

# 类变量可以通过类去访问
print("MyClass.count:",MyClass.count) # 0 

# 类变量也可以通过实例访问
a = MyClass()
print("a.count:",a.count) # 0 

实例的类变量和类中的类变量,最初是指向同一个地址

print(f"MyClass.count ID: {id(MyClass.count)}") # 2601388933328
print(f"a.count ID: {id(a.count)}") #  2601388933328

修改实例中的类变量,并不会修改类中的类变量

a.count = 1
print(f"a.count: {a.count}  ID: {id(a.count)}") # 2601388933360 指向了新的地址
print(f"MyClass.count: {MyClass.count}  ID: {id(MyClass.count)}") # 2601388933328 仍是指向之前的地址

修改类变量,会导致所有实例的类变量也跟着改变。除非该实例在之前修改过类变量

b = MyClass()
MyClass.count = 9 # 修改类变量
# 类中的类变量指向了新的地址
print(f"MyClass.count: {MyClass.count}  ID: {id(MyClass.count)}") # 2601388933616

# b实例的类变量也改变了
print(f"b.count: {b.count}  ID: {id(b.count)}") # 2601388933616

# 由于a实例之前修改过类变量,所以不受影响
print(f"a.count: {a.count}  ID: {id(a.count)}") # 2601388933360

# 此后新建的实例,都会引用改变后的值
c = MyClass()
print(f"c.count: {c.count}  ID: {id(c.count)}") # 2601388933616

5、成员变量(Instance Variable):成员变量是定义在类实例上的变量,每个类实例都有自己的一组成员变量。成员变量通常用于表示与实例相关的状态或数据。

示例代码:

class MyClass:
    def __init__(self):
        self.count = 0 # 成员变量
 
my_object = MyClass()
print(my_object.count) # 0
my_object.count = 1
print(my_object.count) # 1