Python类中方法种类介绍

Python类中方法种类介绍

类方法的种类及说明:

方法类型 说明/ 描述
1. 实例方法 1).无特定装饰器,第一个参数为 "self"(指向实例对象)。 2).可通过"self.属性名" 访问实例属性,也可通过"self.class.属性名"或"类名.属性名"访问类属性。 3).应通过 "实例.方法名()" 方式调用;使用"类名.方法名()"需手动传入实例self,不推荐。
2. 类方法 1). 使用"@classmethod"装饰,第一个参数为"cls"(指向类本身)。 2).可通过"cls.属性名" 访问类属性;无法直接访问实例属性(因不绑定具体实例)。 3).可通过"类.方法名()"或"实例.方法名()" 调用,两种方式均自动传递"cls"参数。
3. 静态方法 1). 使用 "@staticmethod"装饰,无强制参数(不绑定"cls" 或"self")。 2).通常不访问类或实例属性;如需访问类属性,可通过"类名.属性名",但不符合静态方法设计初衷。 3).可通过"类.方法名()"或"实例.方法名()"调用,无参数自动传递。
4. 抽象方法 1. 使用 `@abstractmethod` 装饰,必须定义在继承自 `abc.ABC` 的抽象基类中。 2.必须由子类实现,否则子类无法实例化。 3.可为实例方法(参数"self")或类方法(参数"cls"),具体由子类实现决定。
5. 魔术方法 1).以双下划线开头和结尾(如"init"、"str")。 2).由 Python 解释器自动调用,用于实现对象的初始化、表示、运算等底层行为。 3).不应手动直接调用,而应通过相应内置函数或操作符触发。
6. 特性方法 1).使用"@property"装饰,将方法转换为"只读属性"。 2).调用时无需括号,如 "obj.属性"。 3).可配合"@属性名.setter"和"@属性名.deleter"定义设置和删除逻辑,实现对属性的封装与控制。

下面给出示例解释

1. 实例方法示例

python 复制代码
class Student:
    class_attr = "学生类"  # 类属性(所有实例共享)
    
    def __init__(self, name):
        self.name = name  # 实例属性(每个实例独有)
    
    def introduce(self):  # 实例方法
        # 可以访问实例属性和类属性
        print(f"我叫{self.name},属于{self.class_attr}")
    
    def get_class_attr(self):
        # 三种访问类属性的方式(推荐使用前两种)
        print(f"方式1: {self.__class__.class_attr}")    # 通过__class__
        print(f"方式2: {Student.class_attr}")           # 通过类名
        print(f"方式3: {self.class_attr}")              # 通过self(会先在实例中查找)

# 调用
stu = Student("小明")
stu.introduce()  # 正确调用方式

运行输出:

我叫小明,属于学生类

**说明,**易错点和注意事项:

1). 忘记写self参数会导致TypeError

错误示例: def introduce(): 缺少self参数

2). 通过类名调用实例方法时必须手动传入实例

正确但繁琐: Student.introduce(stu)

3). self.class_attr 会先在实例属性中查找,找不到才去类属性中查找

如果存在同名的实例属性,可能得到意外结果

2. 类方法示例

python 复制代码
class Student:
    count = 0  # 类属性
    
    def __init__(self, name):
        self.name = name
        Student.count += 1  # 修改类属性
    
    @classmethod
    def get_count(cls):  # 类方法
        # cls 指向类本身,不是实例
        return f"学生总数:{cls.count}"  # 通过cls访问类属性
    
    @classmethod
    def from_string(cls, info_str):  # 类方法作为工厂方法
        # 常用于创建实例的替代构造方法
        name = info_str.split(",")[0]
        return cls(name)  # 相当于调用 Student(name)
    
    @classmethod
    def try_access_instance_attr(cls):
        # 这里无法访问实例属性,因为不知道是哪个实例
        # print(self.name)  # 错误!没有self
        # print(cls.name)   # 错误!类没有name属性
        pass

# 调用
stu1 = Student("张三")
stu2 = Student("李四")
print(Student.get_count())  # 通过类调用
print(stu1.get_count())     # 通过实例调用(不推荐)

运行输出

学生总数:2

学生总数:2

说明,易错点和注意事项:

1). 类方法无法访问实例属性,因为不绑定具体实例

2). 类方法中修改类属性会影响所有实例

3). 通过实例调用类方法虽然可行,但不推荐,容易引起混淆

4). 类方法常用于工厂模式、计数器、类级别配置等场景

3. 静态方法示例

python 复制代码
class MathUtils:
    PI = 3.14159  # 类属性
    
    @staticmethod
    def add(a, b):  # 静态方法
        # 不接收self或cls参数
        return a + b
    
    @staticmethod
    def is_even(number):
        return number % 2 == 0
    
    @staticmethod
    def calculate_circle_area(radius):
        # 虽然可以通过类名访问类属性,但这不符合静态方法的设计初衷
        # 静态方法应该是纯粹的工具函数,不依赖类状态
        return MathUtils.PI * radius ** 2  # 不推荐这样做
    
    @staticmethod
    def bad_practice():
        # 静态方法中不应该这样做:
        # print(self.name)  # 错误!没有self
        # print(cls.PI)     # 错误!没有cls
        pass

# 调用
print(MathUtils.add(5, 3))      # 推荐:通过类调用
util = MathUtils()
print(util.add(2, 2))          # 可行但不推荐:通过实例调用

运行输出:

8

4

**说明,**易错点和注意事项:

1). 静态方法既不能访问实例属性,也不能直接访问类属性

2). 如果需要访问类属性,应该考虑使用类方法

3). 静态方法应该是无状态的工具函数

4). 通过实例调用静态方法可能让人误解该方法与实例状态有关

4. 抽象方法示例

python 复制代码
from abc import ABC, abstractmethod

class Animal(ABC):  # 抽象基类
    def __init__(self, name):
        self.name = name
    
    @abstractmethod
    def make_sound(self):  # 抽象实例方法
        # 只有方法定义,没有实现
        pass
    
    @classmethod
    @abstractmethod
    def animal_type(cls):  # 抽象类方法
        # 抽象方法也可以是类方法
        pass
    
    def normal_method(self):
        # 抽象类中可以包含具体方法
        return f"{self.name}是动物"

class Dog(Animal):  # 具体子类
    def make_sound(self):  # 必须实现所有抽象方法
        return "汪汪!"
    
    @classmethod
    def animal_type(cls):
        return "哺乳动物"

# 使用
dog = Dog("旺财")
print(dog.make_sound())

运行输出:

汪汪!

**说明,**易错点和注意事项:

1). 忘记实现抽象方法会导致TypeError

2). 抽象类不能被实例化,只能被继承

3). @abstractmethod必须放在最内层装饰器位置

4). 抽象类中可以包含具体方法,子类可以直接继承使用

5). 抽象方法可以有实现,但通常不提供(通过super()调用)

错误示例:

animal = Animal("抽象动物") TypeError!

5. 魔术方法示例

运行输出:

汪汪!

**说明,**易错点和注意事项:

1). 忘记实现抽象方法会导致TypeError

2). 抽象类不能被实例化,只能被继承

3). @abstractmethod必须放在最内层装饰器位置

4). 抽象类中可以包含具体方法,子类可以直接继承使用

5). 抽象方法可以有实现,但通常不提供(通过super()调用)

错误示例:

animal = Animal("抽象动物") TypeError!

5. 魔术方法示例

python 复制代码
class Book:
    def __init__(self, title, author, pages=0):  # 构造方法
        # 在对象创建时自动调用
        self.title = title
        self.author = author
        self.pages = pages
    
    def __str__(self):  # 字符串表示
        # 被print()、str()调用
        return f"《{self.title}》 - {self.author}"
    
    def __repr__(self):  # 解释器表示
        # 在交互式环境中显示,被repr()调用
        return f"Book('{self.title}', '{self.author}')"
    
    def __len__(self):  # 定义长度
        # 被len()调用
        return self.pages
    
    def __add__(self, other):  # 加法运算
        # 被+操作符调用
        if isinstance(other, Book):
            return f"{self.title} & {other.title}"
        return NotImplemented
    
    def __eq__(self, other):  # 相等判断
        # 被==操作符调用
        if isinstance(other, Book):
            return self.title == other.title and self.author == other.author
        return False

# 使用
book1 = Book("Python编程", "John", 300)
book2 = Book("算法导论", "Jane", 500)

print(book1)           # 自动调用__str__
print(len(book1))      # 自动调用__len__
print(book1 + book2)   # 自动调用__add__
print(book1 == book2)  # 自动调用__eq__

运行输出:

《Python编程》 - John

300

Python编程 & 算法导论

False

**说明,**易错点和注意事项:

1). 魔术方法由Python自动调用,不应手动直接调用

2). 不同的魔术方法需要返回特定类型(如__len__返回整数)

3). 运算符重载时应考虑类型检查,对不支持的类型返回NotImplemented

4). 同时实现__str__和__repr__,__repr__应该包含重建对象的信息

5). 某些魔术方法需要成对实现(如__eq__和__ne__)

6. 特性方法示例

python 复制代码
class Circle:
    def __init__(self, radius):
        # 使用_开头表示受保护的属性
        self._radius = radius
        self._diameter = radius * 2  # 缓存计算值
    
    @property
    def radius(self):  # 只读属性
        # 像属性一样访问:circle.radius
        return self._radius
    
    @property
    def area(self):  # 计算属性
        # 每次访问时动态计算
        return 3.14 * self._radius ** 2
    
    @property
    def diameter(self):
        # 可以返回缓存值以提高性能
        return self._diameter
    
    @diameter.setter
    def diameter(self, value):  # setter方法
        # 在赋值时进行验证和计算
        if value <= 0:
            raise ValueError("直径必须大于0")
        self._radius = value / 2
        self._diameter = value  # 更新缓存
    
    @radius.deleter
    def radius(self):  # deleter方法
        # 定义删除属性时的行为
        print("删除半径属性")
        del self._radius

# 使用
circle = Circle(5)
print(circle.radius)     # 像属性一样访问,无需括号
print(circle.area)       # 自动计算
print(circle.diameter)   # 使用缓存值

circle.diameter = 14     # 通过setter设置,会自动更新radius
print(circle.radius)     # 输出: 7

# del circle.radius      # 会调用deleter方法

运行输出:

5

78.5

10

7.0

**说明,**易错点和注意事项:

1). @property必须定义在@setter之前

2). setter和deleter的方法名必须与property方法名相同

3). 使用property后,方法调用不需要括号

4). 可以在setter中添加数据验证逻辑

5). 对于计算密集型属性,可以考虑缓存计算结果

6). 避免在property方法中进行耗时操作

附录

Python青少年简明教程:类和对象入门 https://blog.csdn.net/cnds123/article/details/141953553

Python面向对象程序设计讲座 https://blog.csdn.net/cnds123/article/details/108354860

Python中的property介绍 https://blog.csdn.net/cnds123/article/details/129420059

相关推荐
麦麦鸡腿堡2 小时前
Java_LinkedList底层结构
java·开发语言
whatever who cares3 小时前
android/java中gson的用法
android·java·开发语言
用户8356290780513 小时前
使用Python合并Word文档:实现高效自动化办公
后端·python
周杰伦fans3 小时前
C# 中 Entity Framework (EF) 和 EF Core 里的 `AsNoTracking` 方法
开发语言·c#
小灰灰搞电子3 小时前
Rust Slint实现控件尺寸的扩展与收缩源码分享
开发语言·后端·rust
☆cwlulu3 小时前
git分支管理详解
开发语言·git·青少年编程
hashiqimiya3 小时前
harmonyos的鸿蒙的跳转页面的部署
开发语言·前端·javascript
零基础的修炼3 小时前
Linux---序列化与反序列化
java·开发语言
敲代码的嘎仔3 小时前
JavaWeb零基础学习Day6——JDBC
java·开发语言·sql·学习·spring·单元测试·maven