文章

Python学习笔记之类

1 类练习一

你有一个形如 $ax^2+bx+c$ 的多项式,你要支持如下的操作:

  • 1 A B C 将当前多项式加上 $Ax^2+Bx+C$。
  • 2 A 将当前多项式加上 $Ax^2+Ax+A$。
  • 3 询问 $ax^2+bx+c=0$ 解的个数。
  • 4 输出当前多项式。

1.1 示例程序:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
class MyClass:
    import math
    def __init__(self, a, b, c):
        self.a = a
        self.b = b
        self.c = c

    def __add__(self, other):
        return MyClass(self.a + other.a, self.b + other.b, self.c + other.c)

    def add(self, A):
        self.a += A
        self.b += A
        self.c += A

    @staticmethod
    def que(poly):
        a, b, c = poly.a, poly.b, poly.c
        if a == 0:
            if b == 0:
                return 0 if c != 0 else float('inf')
            return 1
        discriminant = b * b - 4 * a * c
        if discriminant > 0:
            return 2
        elif discriminant == 0:
            return 1
        else:
            return 0

    def __str__(self):
        a_str = str(self.a)
        if self.b >= 0:
            b_str = "+" + str(self.b)
        else:
            b_str = "-" + str(-self.b)
        if self.c >= 0:
            c_str = "+" + str(self.c)
        else:
            c_str = "-" + str(-self.c)
  
        if self.b == 0 and self.c == 0:
            return a_str + "*x^2"
        elif self.b == 0:
            return a_str + "*x^2" + c_str
        elif self.c == 0:
            return a_str + "*x^2" + b_str + "*x"
        else:
            return a_str + "*x^2" + b_str + "*x" + c_str

1.2 特殊方法与普通方法

首先我们注意到,有些函数是由带着前后的 __ ,而有些函数是直接的名称。在 Python 中,带有双下划线 __ 的函数(称为“特殊方法”或“魔法方法”)与普通方法有几个显著的区别:

1.2.1 特殊方法(魔法方法)

  • 定义: 特殊方法是以双下划线开始和结束的方法,例如 __init__, __add__, __str__, __eq__ 等。
  • 目的: 这些方法是 Python 的内置机制的一部分,提供了对 Python 内建操作的自定义。它们允许用户定义对象的行为,使其能够响应特定的操作或行为。
  • 用法:

    • __init__: 构造函数,用于初始化对象。
    • __add__: 实现加法操作 (+) 的行为。
    • __str__: 定义对象的字符串表示。
    • __eq__: 定义对象的相等性比较(==)。
    • __call__: 使对象能够像函数一样被调用。

    这些方法通常不直接调用,而是通过运算符或内置函数间接调用。例如,obj + other 会调用 obj.__add__(other)

  • 特殊性: 特殊方法在 Python 内部有特殊的作用,它们定义了对象在特定操作中的行为。它们是 Python 数据模型的一部分,并且可以被 Python 的内置函数和操作所自动调用。

1.2.2 普通方法

  • 定义: 普通方法是类中定义的以单个下划线或没有下划线的函数,例如 add, subtract, display 等。
  • 目的: 这些方法用于定义类的实例可以执行的行为或操作。它们通常用于实现类的业务逻辑。
  • 用法:

    • add: 例如,用于执行类实例的某个具体操作,可能改变实例的状态或执行计算。
    • display: 显示对象的状态或信息。

    普通方法可以被实例通过点运算符调用,例如 obj.add(value)

  • 特殊性: 普通方法不具备特殊的内置功能或自动触发机制,它们是用户定义的用于实现类功能的普通函数。

1.2.3总结

  • 特殊方法:

    • 由双下划线包围(如 __init__, __add__)。
    • 与 Python 内部机制和运算符操作相关。
    • 通常不直接调用,而是通过 Python 内置操作间接调用。
    • 用于自定义对象在内建操作中的行为。
  • 普通方法:

    • 没有双下划线。
    • 用于实现类的具体业务逻辑。
    • 通过对象实例直接调用。

1.3代码详解

1.3.1 导入模块

1
import math
  • import math:导入 Python 的数学模块。

1.3.2 初始化函数 __init__

1
2
3
4
def __init__(self, a, b, c):
    self.a = a
    self.b = b
    self.c = c
  • 功能: 构造函数,用于初始化 MyClass 的实例。
  • 参数:

    • a:二次项的系数。
    • b:一次项的系数。
    • c:常数项的系数。
  • 作用: 当创建 MyClass 的实例时,abc 将被赋值给实例的属性 self.aself.bself.c

1.3.3 加法运算符重载 __add__

1
2
def __add__(self, other):
    return MyClass(self.a + other.a, self.b + other.b, self.c + other.c)
  • 功能: 实现加法运算符 +重载,使得两个 MyClass 实例可以通过 + 操作符相加。
  • 参数:
    • other:另一个 MyClass 实例。
  • 返回: 返回一个新的 MyClass 实例,其系数是两个实例对应系数的和。

1.3.4 修改系数 add

1
2
3
4
def add(self, A):
    self.a += A
    self.b += A
    self.c += A
  • 功能: 将指定值 A 加到多项式的所有系数上。
  • 参数:
    • A:要加到每个系数的值。
  • 作用: 修改当前实例的系数 abc,使它们都增加 A

1.3.5 静态方法 que

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@staticmethod
def que(poly):
    a, b, c = poly.a, poly.b, poly.c
    if a == 0:
        if b == 0:
            return 0 if c != 0 else float('inf')
        return 1
    discriminant = b * b - 4 * a * c
    if discriminant > 0:
        return 2
    elif discriminant == 0:
        return 1
    else:
        return 0
  • 功能: 求解二次方程 ax^2 + bx + c = 0 的根的个数。
  • 参数:
    • polyMyClass 的实例,表示一个二次多项式。
  • 返回:
    • 0:无实根。
    • 1:有一个实根(重根)。
    • 2:有两个不同的实根。
    • float('inf'):当 ab 都为 0c 不为 0 时,返回无解。

1.3.6 字符串表示 __str__

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
def __str__(self):
    a_str = str(self.a)
    if self.b >= 0:
        b_str = "+" + str(self.b)
    else:
        b_str = "-" + str(-self.b)
    if self.c >= 0:
        c_str = "+" + str(self.c)
    else:
        c_str = "-" + str(-self.c)
  
    if self.b == 0 and self.c == 0:
        return a_str + "*x^2"
    elif self.b == 0:
        return a_str + "*x^2" + c_str
    elif self.c == 0:
        return a_str + "*x^2" + b_str + "*x"
    else:
        return a_str + "*x^2" + b_str + "*x" + c_str
  • 功能: 返回多项式的字符串表示形式。
  • 构造:
    • a_strb_strc_str:分别表示 abc 的字符串形式。
    • 根据 bc 的符号,格式化字符串,确保 +- 正确显示。
  • 返回: 多项式的标准字符串格式,如 2*x^2 - 3*x + 4

1.4 静态方法修饰器

在 Python 中,静态方法(@staticmethod)和普通方法(实例方法)有以下主要区别:

1.4.1 定义和调用方式

  • 静态方法(@staticmethod:
    • 定义: 使用 @staticmethod 装饰器定义的方法,不需要 self 参数。
    • 调用: 可以通过类或实例调用,且不依赖于类的实例。调用时不传递实例或类作为参数。
    • 示例:
      1
      2
      3
      4
      5
      6
      
      class MyClass:
          @staticmethod
          def my_static_method():
              print("This is a static method")
      
      MyClass.my_static_method()  # 通过类调用
      
  • 普通方法(实例方法):
    • 定义: 普通方法定义时需要 self 参数,用于访问实例的属性和其他方法。
    • 调用: 必须通过类的实例来调用,调用时自动传递实例作为第一个参数。
    • 示例:
      1
      2
      3
      4
      5
      6
      
      class MyClass:
          def my_instance_method(self):
              print("This is an instance method")
      
      obj = MyClass()
      obj.my_instance_method()  # 通过实例调用
      

1.4.2 访问权限

  • 静态方法:
    • 不访问类的属性或实例的属性。
    • 适合执行与类的实例无关的任务,如工具函数或辅助函数。
  • 普通方法:
    • 可以访问和修改实例的属性和方法。
    • 适合实现与实例状态相关的操作和行为。

1.4.3. 使用场景

  • 静态方法:
    • 用于实现功能性代码,与对象的状态无关。
    • 适合需要与类相关,但不依赖于类或实例状态的函数。
  • 普通方法:
    • 用于操作实例的状态或执行依赖于实例的操作。
    • 适合需要访问和修改对象的内部数据或状态的函数。

2 拓展:关于类的其他修饰器

除了 @staticmethod 和普通方法,还有其他几种常用的类修饰器(装饰器)和方法修饰器,主要包括:

2.1 类方法(@classmethod

  • 定义: 使用 @classmethod 装饰器定义的方法,第一个参数是 cls,表示类本身,而不是实例。
  • 调用: 可以通过类或实例调用。调用时自动传递类作为第一个参数。
  • 用途: 适合访问或修改类的状态(而非实例状态),例如工厂方法或替代构造函数。
  • 示例:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    
    class MyClass:
        class_var = 0
    
        @classmethod
        def increment_class_var(cls):
            cls.class_var += 1
    
        @classmethod
        def create_instance(cls):
            return cls()
    
    MyClass.increment_class_var()  # 通过类调用
    instance = MyClass.create_instance()  # 通过类调用
    

2.2 属性方法(@property

  • 定义: 使用 @property 装饰器定义的方法,使其表现得像一个属性,而不是方法。
  • 调用: 通过访问属性的方式调用,而不是通过方法调用。
  • 用途: 适合将计算结果或只读值暴露为属性而不是方法。
  • 示例:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    
    class MyClass:
        def __init__(self, value):
            self._value = value
    
        @property
        def value(self):
            return self._value
    
        @value.setter
        def value(self, new_value):
            self._value = new_value
    
    obj = MyClass(10)
    print(obj.value)  # 通过属性访问
    obj.value = 20  # 通过属性设置
    

2.3 只读属性方法(@property 的只读部分)

  • 定义: @property 使方法表现为只读属性,不提供 setter 方法。
  • 用途: 适合提供只读的属性访问,而不允许修改。
  • 示例:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    
    class MyClass:
        def __init__(self, value):
            self._value = value
    
        @property
        def value(self):
            return self._value
    
    obj = MyClass(10)
    print(obj.value)  # 通过属性访问
    # obj.value = 20  # AttributeError: can't set attribute
    

2.4 @staticmethod@classmethod 的组合

  • 定义: 可以在一个类中同时使用静态方法和类方法,以实现不同的功能需求。
  • 示例:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    
    class MyClass:
        @staticmethod
        def static_method():
            print("This is a static method")
    
        @classmethod
        def class_method(cls):
            print("This is a class method")
    
    MyClass.static_method()
    MyClass.class_method()
    
本文由作者按照 CC BY 4.0 进行授权

© Dignite. 保留部分权利。 由  提供CDN加速。

浙ICP备2023032699号 | 使用 Jekyll 主题 Chirpy