文章

魔法函数指南

一、简介

魔法方法(magic methods)是 Python 中的特殊方法,其名称以双下划线开头和结尾(例如 __init__),用于在类定义中实现特定功能的功能。

Python 解释器根据特定的魔法方法来执行对象的操作。例如,当我们创建一个新的对象时,解释器自动调用对象的 __new__ 方法来分配内存,并使用对象的 __init__ 方法进行初始化。当我们使用 + 运算符将两个对象相加时,解释器自动调用对象的 __add__ 方法来实现加法操作。

魔法方法可以使开发者更加方便地控制类的行为,同时也提供了一些有用的功能,例如自定义对象的打印输出、格式化字符串、属性访问和设置、运算符重载等。

在 Python 中,魔法方法非常丰富,涵盖了各种不同的功能和用途。熟练掌握这些魔法方法,可以大幅提高代码的可读性和灵活性,并且能够更加深入地理解 Python 语言的本质。

二、 分类

根据其功能和使用场景的不同,魔法方法可以分为以下几类(由于排版问题,想看代码实例可全局搜索):

1. 对象创建和初始化类:

  • __new__(cls, ...): 用于创建对象。
  • __init__(self, ...): 用于初始化对象。

2. 对象表示和转换:

  • __str__(self): 定义了该类的实例被打印时的输出内容。
  • __repr__(self): 定义了该类的实例在交互模式下被调用时的输出内容。
  • __format__(self, format_spec): 定义了该类的实例被格式化时的输出形式。
  • __bytes__(self): 定义了该类的实例被转换成字节序列的方式。

3. 属性访问和设置:

  • __getattr__(self, name): 在对象的属性未找到时被调用。
  • __getattribute__(self, name): 在对象的属性被访问时被调用。
  • __setattr__(self, name, value): 在对象的属性被设置时被调用。
  • __delattr__(self, name): 在对象的属性被删除时被调用。

4. 运算符重载:

  • __eq__(self, other): 定义了相等操作符(==)的实现。
  • __ne__(self, other): 定义了不等于操作符(!=)的实现。
  • __lt__(self, other): 定义了小于操作符(<)的实现。
  • __le__(self, other): 定义了小于等于操作符(<=)的实现。
  • __gt__(self, other): 定义了大于操作符(>)的实现。
  • __ge__(self, other): 定义了大于等于操作符(>=)的实现。
  • __add__(self, other): 定义了加法操作符(+)的实现。
  • __sub__(self, other): 定义了减法操作符(-)的实现。
  • __mul__(self, other): 定义了乘法操作符(*)的实现。
  • __truediv__(self, other): 定义了真除法操作符(/)的实现。
  • __floordiv__(self, other): 定义了整除法操作符(//)的实现。
  • __mod__(self, other): 定义了取模操作符(%)的实现。
  • __pow__(self, other [, modulo]): 定义了幂次方操作符(**)的实现。
  • __and__(self, other): 定义了按位与操作符(&)的实现。
  • __or__(self, other): 定义了按位或操作符(|)的实现。
  • __xor__(self, other): 定义了按位异或操作符(^)的实现。
  • __lshift__(self, other): 定义了左移操作符(«)的实现。
  • __rshift__(self, other): 定义了右移操作符(»)的实现。

5. 序列和映射:

  • __len__(self): 定义了该类的实例长度,即元素的个数。
  • __getitem__(self, key): 定义了该类的实例通过索引访问元素的方式。
  • __setitem__(self, key, value): 定义了该类的实例通过索引设置元素的方式。
  • __delitem__(self, key): 定义了该类的实例通过索引删除元素的方式。
  • __iter__(self): 定义了该类的实例可迭代的方式。
  • __reversed__(self): 定义了该类的实例反向迭代

三、 代码实例

以下是这些魔法方法的使用实例:

__new__(cls, …) 方法是创建对象时第一个被调用的方法,它用于创建并返回一个新的实例对象。我们可以通过重载这个方法,自定义对象的创建方式。

下面是一个使用 __new__ 创建单例模式的示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Singleton:
  _instance = None

  def __new__(cls, *args, **kwargs):
    if cls._instance is None:
      cls._instance = super().__new__(cls, *args, **kwargs)
    return cls._instance


s1 = Singleton()
s2 = Singleton()

print(s1 is s2)  # 输出 True

在此示例中,我们定义了一个名为 Singleton 的类,它只能创建一个实例对象。我们通过重载 __new__ 方法,创建一个 _instance 类属性,用于保存当前已经创建的实例对象。在每次创建实例对象时,我们首先检查 _instance 是否为空,如果为空则创建新的实例对象;否则返回已经存在的实例对象。

在以上示例中,我们创建了两个实例对象 s1 和 s2,但是它们实际上是同一个对象,因此输出结果为 True。这就是单例模式的应用场景之一。

__str__(self)

__str__ 方法定义了该类的实例被打印时的输出内容。我们可以通过重载这个方法,自定义对象被打印时输出的字符串。

1
2
3
4
5
6
7
8
9
10
class MyClass:
    def __init__(self, name):
        self.name = name
    
    def __str__(self):
        return f"MyClass: {self.name}"
    
obj = MyClass("foo")

print(obj) # 输出 "MyClass: foo"

在此示例中,我们定义了一个名为 MyClass 的类,它有一个属性 name 表示对象的名称。通过重载 __str__ 方法,我们定义了对象被打印时输出的字符串。

__repr__(self)

__repr__ 方法定义了该类的实例在交互模式下被调用时的输出内容。我们可以通过重载这个方法,自定义对象在交互模式下被调用时输出的字符串。

1
2
3
4
5
6
7
8
9
10
class MyClass:
    def __init__(self, name):
        self.name = name
    
    def __repr__(self):
        return f"MyClass('{self.name}')"
    
obj = MyClass("foo")

obj # 在交互模式下输出 "MyClass('foo')"

在此示例中,我们定义了一个名为 MyClass 的类,它有一个属性 name 表示对象的名称。通过重载 __repr__ 方法,我们定义了对象在交互模式下被调用时输出的字符串。

__format__(self, format_spec)

__format__ 方法定义了该类的实例被格式化时的输出形式。我们可以通过重载这个方法,自定义对象被格式化时输出的字符串。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class MyClass:
    def __init__(self, value):
        self.value = value
    
    def __format__(self, format_spec):
        if format_spec == "hex":
            return hex (self.value)
        elif format_spec == "bin":
            return bin (self.value)
        else:
            return str (self.value)
            
obj = MyClass(42)

print("Value in hex: {:hex}".format (obj)) # 输出 "Value in hex: 0x2a"
print("Value in binary: {:bin}".format (obj)) # 输出 "Value in binary: 0b101010"

在此示例中,我们定义了一个名为 MyClass 的类,它有一个属性 value 表示对象的值。通过重载 __format__ 方法,我们定义了对象被格式化时的输出形式,使得可以通过 {} 格式化字符串时指定不同的格式。

__bytes__(self)

__bytes__ 方法定义了该类的实例被转换成字节序列的方式。我们可以通过重载这个方法,自定义对象被转换成字节序列的逻辑。

1
2
3
4
5
6
7
8
9
10
class MyClass:
    def __init__(self, value):
        self.value = value
    
    def __bytes__(self):
        return bytes ([self.value])
    
obj = MyClass(65)

print(bytes (obj)) # 输出 b'A'

在此示例中,我们定义了一个名为 MyClass 的类,它有一个属性 value 表示对象的值。通过重载 __bytes__ 方法,我们定义了对象被转换成字节序列的逻辑。

__getattr__(self, name)

__getattr__ 方法在对象的属性未找到时被调用。我们可以利用 __getattr__ 方法动态地返回对象的属性值或者执行一些额外的操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
class MyClass:
    x = 10
    
    def __getattr__(self, name):
        if name == 'y':
            return 20
        else:
            raise AttributeError ('Attribute not found')
    
obj = MyClass()
print(obj.x)  # 输出 10
print(obj.y)  # 输出 20
print(obj.z)  # 抛出 AttributeError 异常

在此示例中,如果尝试访问 obj 对象中不存在的属性 z,则会抛出 AttributeError 异常。但是如果访问 obj 对象中不存在的属性 y,则会返回一个固定的值 20,这是通过 __getattr__ 方法实现的。

__getattribute__(self, name)

__getattribute__ 方法在对象的属性被访问时被调用。它与 __getattr__ 方法类似,但是不同之处在于,它必须返回一个值,否则将抛出异常。

1
2
3
4
5
6
7
8
9
10
11
12
13
class MyClass:
    x = 10
    
    def __getattribute__(self, name):
        if name == 'y':
            return 20
        else:
            return object.__getattribute__(self, name)
    
obj = MyClass()
print(obj.x)  # 输出 10
print(obj.y)  # 输出 20
print(obj.z)  # 抛出 AttributeError 异常

在此示例中,如果尝试访问 obj 对象中不存在的属性 z,则会抛出 AttributeError 异常。但是如果访问 obj 对象中不存在的属性 y,则会返回一个固定的值 20,这是通过 __getattribute__ 方法实现的。

__setattr__(self, name, value)

__setattr__ 方法在对象的属性被设置时被调用。我们可以利用 setattr 方法动态地修改对象的属性值或者执行一些额外的操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
class MyClass:
    x = 10
    
    def __setattr__(self, name, value):
        if name == 'y':
            raise AttributeError ('Cannot set attribute')
        else:
            object.__setattr__(self, name, value)
    
obj = MyClass()
obj.x = 20
print(obj.x)  # 输出 20
obj.y = 30  # 抛出 AttributeError 异常

在此示例中,如果尝试修改 obj 对象中特定的属性 y,则会抛出 AttributeError 异常。但是如果修改 obj 对象中其他的属性,例如 x,则不会有异常发生。

__delattr__(self, name)

__delattr__ 方法在对象的属性被删除时被调用。我们可以利用 __delattr__ 方法动态地删除对象的属性或者执行一些额外的操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
class MyClass:
    x = 10
    
    def __delattr__(self, name):
        if name == 'y':
            raise AttributeError ('Cannot delete attribute')
        else:
            object.__delattr__(self, name)
    
obj = MyClass()
del obj.x
print(hasattr (obj, 'x'))  # 输出 False
del obj.y  # 抛出 AttributeError 异常

在此示例中,如果尝试删除 obj 对象中特定的属性 y,则会抛出 AttributeError 异常。但是如果删除 obj 对象中其他的属性,例如 x,则不会有异常发生。

__eq__(self, other)

__eq__ 方法定义了相等操作符(==)的实现。我们可以通过重载这个方法,自定义对象相等的比较方式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Vector:
    def __init__(self, x, y):
        self.x = x
        self.y = y
    
    def __eq__(self, other):
        return self.x == other.x and self.y == other.y
    
v1 = Vector(1, 2)
v2 = Vector(1, 2)
v3 = Vector(2, 3)

print(v1 == v2)  # 输出 True
print(v1 == v3)  # 输出 False

在此示例中,我们定义了一个名为 Vector 的类,它有两个属性 x 和 y。通过重载 __eq__ 方法,我们定义了对象相等的比较方式,当两个向量的 x 和 y 值都相等时,它们被认为是相等的。

__ne__(self, other)

__ne__ 方法定义了不等于操作符(!=)的实现。我们可以通过重载这个方法,自定义对象不等的比较方式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Vector:
    def __init__(self, x, y):
        self.x = x
        self.y = y
    
    def __ne__(self, other):
        return not self.__eq__(other)
    
v1 = Vector(1, 2)
v2 = Vector(1, 2)
v3 = Vector(2, 3)

print(v1 != v2)  # 输出 False
print(v1 != v3)  # 输出 True

在此示例中,我们定义了一个名为 Vector 的类,它有两个属性 x 和 y。通过重载 __ne__ 方法,我们定义了对象不等的比较方式,当两个向量的 x 和 y 值至少有一个不相等时,它们被认为是不相等的。

__lt__(self, other)

__lt__ 方法定义了小于操作符(<)的实现。我们可以通过重载这个方法,自定义对象大小的比较方式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Vector:
    def __init__(self, x, y):
        self.x = x
        self.y = y
    
    def __lt__(self, other):
        return self.x < other.x and self.y < other.y
    
v1 = Vector(1, 2)
v2 = Vector(2, 3)
v3 = Vector(0, 1)

print(v1 < v2)  # 输出 True
print(v1 < v3)  # 输出 False

在此示例中,我们定义了一个名为 Vector 的类,它有两个属性 x 和 y。通过重载 __lt__ 方法,我们定义了对象大小的比较方式,当一个向量在 x 和 y 坐标上都小于另一个向量时,它被认为是小于另一个向量。

__le__(self, other)

__le__ 方法定义了小于等于操作符(<=)的实现。我们可以通过重载这个方法,自定义对象大小的比较方式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Vector:
    def __init__(self, x, y):
        self.x = x
        self.y = y
    
    def __le__(self, other):
        return self.x <= other.x and self.y <= other.y
    
v1 = Vector(1, 2)
v2 = Vector(2, 3)
v3 = Vector(0, 1)

print(v1 <= v2)  # 输出 True
print(v1 <= v3)  # 输出 False
print(v1 <= v1)  # 输出 True

在此示例中,我们定义了一个名为 Vector 的类,它有两个属性 x 和 y。通过重载 __le__ 方法,我们定义了对象大小的比较方式,当一个向量在 x 和 y 坐标上都小于等

__gt__(self, other)

__gt__ 方法定义了大于操作符(>)的实现。我们可以通过重载这个方法,自定义对象大小的比较方式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Vector:
    def __init__(self, x, y):
        self.x = x
        self.y = y
    
    def __gt__(self, other):
        return self.x > other.x and self.y > other.y
    
v1 = Vector(2, 3)
v2 = Vector(1, 2)
v3 = Vector(3, 4)

print(v1 > v2)  # 输出 True
print(v1 > v3)  # 输出 False

在此示例中,我们定义了一个名为 Vector 的类,它有两个属性 x 和 y。通过重载 __gt__ 方法,我们定义了对象大小的比较方式,当一个向量在 x 和 y 坐标上都大于另一个向量时,它被认为是大于另一个向量。

__ge__(self, other)

__ge__ 方法定义了大于等于操作符(>=)的实现。我们可以通过重载这个方法,自定义对象大小的比较方式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Vector:
    def __init__(self, x, y):
        self.x = x
        self.y = y
    
    def __ge__(self, other):
        return self.x >= other.x and self.y >= other.y
    
v1 = Vector(2, 3)
v2 = Vector(1, 2)
v3 = Vector(3, 4)

print(v1 >= v2)  # 输出 True
print(v1 >= v3)  # 输出 False
print(v1 >= v1)  # 输出 True

在此示例中,我们定义了一个名为 Vector 的类,它有两个属性 x 和 y。通过重载 __ge__ 方法,我们定义了对象大小的比较方式,当一个向量在 x 和 y 坐标上大于等于另一个向量时,它被认为是大于等于另一个向量。

__add__(self, other)

__add__ 方法定义了加法操作符(+)的实现。我们可以通过重载这个方法,自定义对象相加的逻辑。

1
2
3
4
5
6
7
8
9
10
11
12
13
class Vector:
    def __init__(self, x, y):
        self.x = x
        self.y = y
    
    def __add__(self, other):
        return Vector(self.x + other.x, self.y + other.y)
    
v1 = Vector(1, 2)
v2 = Vector(3, 4)

v3 = v1 + v2
print(v3.x, v3.y)  # 输出 4 6

在此示例中,我们定义了一个名为 Vector 的类,它有两个属性 x 和 y。通过重载 __add__ 方法,我们定义了对象相加的逻辑,将两个向量在 x 和 y 坐标上分别相加得到一个新的向量。

__sub__(self, other)

__sub__ 方法定义了减法操作符(-)的实现。我们可以通过重载这个方法,自定义对象相减的逻辑。

1
2
3
4
5
6
7
8
9
10
11
12
13
class Vector:
    def __init__(self, x, y):
        self.x = x
        self.y = y
    
    def __sub__(self, other):
        return Vector(self.x - other.x, self.y - other.y)
    
v1 = Vector(3, 4)
v2 = Vector(1, 2)

v3 = v1 - v2
print(v3.x, v3.y)  # 输出 2 2

在此示例中,我们定义了一个名为 Vector 的类,它有两个属性 x 和 y。通过重载 __sub__ 方法,我们定义了对象相减的逻辑,将两个向量在 x 和 y 坐标上分别相减得到一个新

__mul__(self, other)

__mul__ 方法定义了乘法操作符(*)的实现。我们可以通过重载这个方法,自定义对象相乘的逻辑。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Vector:
    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.y = y
    
    def __mul__(self, other):
        return Vector(self.x * other.x, self.y * other.y)
    
v1 = Vector(2, 3)
v2 = Vector(3, 4)

v3 = v1 * v2
print(v3.x, v3.y)  # 输出 6 12

在此示例中,我们定义了一个名为 Vector 的类,它有两个属性 x 和 y。通过重载 __mul__ 方法,我们定义了对象相乘的逻辑,将两个向量在 x 和 y 坐标上分别相乘得到一个新的向量。

__truediv__(self, other)

__truediv__ 方法定义了真除法操作符(/)的实现。我们可以通过重载这个方法,自定义对象相除的逻辑。

1
2
3
4
5
6
7
8
9
10
11
12
13
class Vector:
    def __init__(self, x, y):
        self.x = x
        self.y = y
    
    def __truediv__(self, other):
        return Vector(self.x/other.x, self.y/other.y)
    
v1 = Vector(6, 8)
v2 = Vector(2, 4)

v3 = v1 /v2
print(v3.x, v3.y)  # 输出 3.0 2.0

在此示例中,我们定义了一个名为 Vector 的类,它有两个属性 x 和 y。通过重载 __truediv__ 方法,我们定义了对象相除的逻辑,将两个向量在 x 和 y 坐标上分别相除得到一个新的向量。

__floordiv__(self, other)

__floordiv__ 方法定义了整除法操作符(//)的实现。我们可以通过重载这个方法,自定义对象整除的逻辑。

1
2
3
4
5
6
7
8
9
10
11
12
13
class Vector:
    def __init__(self, x, y):
        self.x = x
        self.y = y
    
    def __floordiv__(self, other):
        return Vector(self.x//other.x, self.y//other.y)
    
v1 = Vector(7, 9)
v2 = Vector(2, 4)

v3 = v1 //v2
print(v3.x, v3.y)  # 输出 3 2

在此示例中,我们定义了一个名为 Vector 的类,它有两个属性 x 和 y。通过重载 __floordiv__ 方法,我们定义了对象整除的逻辑,将两个向量在 x 和 y 坐标上分别整除得到一个新的向量。

__mod__(self, other)

__mod__ 方法定义了取模操作符(%)的实现。我们可以通过重载这个方法,自定义对象取模的逻辑。

1
2
3
4
5
6
7
8
9
10
11
12
13
class Vector:
    def __init__(self, x, y):
        self.x = x
        self.y = y
    
    def __mod__(self, other):
        return Vector(self.x % other.x, self.y % other.y)
    
v1 = Vector(7, 9)
v2 = Vector(2, 4)

v3 = v1 % v2
print(v3.x, v3.y)  # 输出 1 1

在此示例中,我们定义了一个名为 Vector 的类,它有两个属性 x 和 y。通过重载 __mod__ 方法,我们定义了对象取模的逻辑,将两个向量在 x 和 y 坐标上分别取模得到一个新的向量。

__pow__(self, other [, modulo])

__pow__ 方法定义了幂次方操作符(**)的实现。我们可以通过重载这个方法,自定义对象的幂运算逻辑。

1
2
3
4
5
6
7
8
9
10
11
12
13
class Vector:
    def __init__(self, x, y):
        self.x = x
        self.y = y
    
    def __pow__(self, other):
        return Vector(self.x ** other.x, self.y ** other.y)
    
v1 = Vector(2, 3)
v2 = Vector(3, 2)

v3 = v1 ** v2
print(v3.x, v3.y)  # 输出 8 9

在此示例中,我们定义了一个名为 Vector 的类,它有两个属性 x 和 y。通过重载 __pow__ 方法,我们定义了对象的幂运算逻辑,将两个向量在 x 和 y 坐标上分别进行幂运算得到一个新的向量。

__and__(self, other)

__and__ 方法定义了按位与操作符(&)的实现。我们可以通过重载这个方法,自定义对象按位与运算的逻辑。

1
2
3
4
5
6
7
8
9
10
11
12
class BinaryNumber:
    def __init__(self, num):
        self.num = num
    
    def __and__(self, other):
        return BinaryNumber(self.num & other.num)
    
b1 = BinaryNumber(0b1100)
b2 = BinaryNumber(0b1010)

b3 = b1 & b2
print(bin (b3.num))  # 输出 '0b1000'

在此示例中,我们定义了一个名为 BinaryNumber 的类,它表示一个二进制数。通过重载 __and__ 方法,我们定义了对象按位与运算的逻辑,将两个二进制数进行按位与运算得到一个新的二进制数。

__or__(self, other)

__or__ 方法定义了按位或操作符(|)的实现。我们可以通过重载这个方法,自定义对象按位或运算的逻辑。

1
2
3
4
5
6
7
8
9
10
11
12
class BinaryNumber:
    def __init__(self, num):
        self.num = num
    
    def __or__(self, other):
        return BinaryNumber(self.num | other.num)
    
b1 = BinaryNumber(0b1100)
b2 = BinaryNumber(0b1010)

b3 = b1 | b2
print(bin (b3.num))  # 输出 '0b1110'

在此示例中,我们定义了一个名为 BinaryNumber 的类,它表示一个二进制数。通过重载 __or__ 方法,我们定义了对象按位或运算的逻辑,将两个二进制数进行按位或运算得到一个新的二进制数。

__xor__(self, other)

__xor__ 方法定义了按位异或操作符(^)的实现。我们可以通过重载这个方法,自定义对象按位异或运算的逻辑。

1
2
3
4
5
6
7
8
9
10
11
12
class BinaryNumber:
    def __init__(self, num):
        self.num = num
    
    def __xor__(self, other):
        return BinaryNumber(self.num ^ other.num)
    
b1 = BinaryNumber(0b1100)
b2 = BinaryNumber(0b1010)

b3 = b1 ^ b2
print(bin (b3.num))  # 输出 '0b0110'

在此示例中,我们定义了一个名为 BinaryNumber 的类,它表示一个二进制数。通过重载 __xor__ 方法,我们定义了对象按位异或运算的逻辑,将两个二进制数进行按位异或运算得到一个新的二进制数。 下面是这些魔法方法的使用实例:

__lshift__(self, other)

__lshift__ 方法定义了左移操作符(«)的实现。我们可以通过重载这个方法,自定义对象的左移运算逻辑。

1
2
3
4
5
6
7
8
9
10
11
class BinaryNumber:
    def __init__(self, num):
        self.num = num
    
    def __lshift__(self, other):
        return BinaryNumber(self.num << other)
    
b1 = BinaryNumber(0b1100)

b2 = b1 << 2
print(bin (b2.num))  # 输出 '0b110000'

在此示例中,我们定义了一个名为 BinaryNumber 的类,它表示一个二进制数。通过重载 __lshift__ 方法,我们定义了对象的左移运算逻辑,将一个二进制数左移指定的位数得到一个新的二进制数。

__rshift__(self, other)

__rshift__ 方法定义了右移操作符(»)的实现。我们可以通过重载这个方法,自定义对象的右移运算逻辑。

1
2
3
4
5
6
7
8
9
10
11
class BinaryNumber:
    def __init__(self, num):
        self.num = num
    
    def __rshift__(self, other):
        return BinaryNumber(self.num >> other)
    
b1 = BinaryNumber(0b1100)

b2 = b1 >> 2
print(bin (b2.num))  # 输出 '0b0011'

在此示例中,我们定义了一个名为 BinaryNumber 的类,它表示一个二进制数。通过重载 __rshift__ 方法,我们定义了对象的右移运算逻辑,将一个二进制数右移指定的位数得到一个新的二进制数。

下面是这些魔法方法的使用示例:

__len__(self)

__len__ 方法定义了该类的实例长度,即元素的个数。我们可以通过重载这个方法,自定义对象的长度逻辑。

1
2
3
4
5
6
7
8
9
10
class MyList:
    def __init__(self, elements):
        self.elements = elements
    
    def __len__(self):
        return len (self.elements)
    
my_list = MyList([1, 2, 3, 4, 5])

print(len (my_list)) # 输出 5

在此示例中,我们定义了一个名为 MyList 的类,它有一个属性 elements 表示列表的元素。通过重载 __len__ 方法,我们定义了对象的长度逻辑,返回列表元素的个数。

__getitem__(self, key)

__getitem__ 方法定义了该类的实例通过索引访问元素的方式。我们可以通过重载这个方法,自定义对象索引访问元素的逻辑。

1
2
3
4
5
6
7
8
9
10
class MyList:
    def __init__(self, elements):
        self.elements = elements
    
    def __getitem__(self, index):
        return self.elements [index]
    
my_list = MyList([1, 2, 3, 4, 5])

print(my_list [2]) # 输出 3

在此示例中,我们定义了一个名为 MyList 的类,它有一个属性 elements 表示列表的元素。通过重载 __getitem__ 方法,我们定义了对象索引访问元素的逻辑,返回列表指定索引位置上的元素。

__setitem__(self, key, value)

__setitem__ 方法定义了该类的实例通过索引设置元素的方式。我们可以通过重载这个方法,自定义对象索引设置元素的逻辑。

1
2
3
4
5
6
7
8
9
10
11
12
class MyList:
    def __init__(self, elements):
        self.elements = elements
    
    def __setitem__(self, index, value):
        self.elements [index] = value
    
my_list = MyList([1, 2, 3, 4, 5])

my_list [2] = 10

print(my_list.elements) # 输出 [1, 2, 10, 4, 5]

在此示例中,我们定义了一个名为 MyList 的类,它有一个属性 elements 表示列表的元素。通过重载 __setitem__ 方法,我们定义了对象索引设置元素的逻辑,将列表指定索引位置上的元素赋值为新值。

__delitem__(self, key)

__delitem__ 方法定义了该类的实例通过索引删除元素的方式。我们可以通过重载这个方法,自定义对象索引删除元素的逻辑。

1
2
3
4
5
6
7
8
9
10
11
12
class MyList:
    def __init__(self, elements):
        self.elements = elements
    
    def __delitem__(self, index):
        del self.elements [index]
    
my_list = MyList([1, 2, 3, 4, 5])

del my_list [2]

print(my_list.elements) # 输出 [1, 2, 4, 5]

在此示例中,我们定义了一个名为 MyList 的类,它有一个属性 elements 表示列表的元素。通过重载 __delitem__ 方法,我们定义了对象索引删除元素的逻辑,将列表指定索引位置上的元素删除。

__iter__(self)

__iter__ 方法定义了该类的实例可迭代的方式。我们可以通过重载这个方法,自定义对象的迭代逻辑。

1
2
3
4
5
6
7
8
9
10
11
class MyList:
    def __init__(self, elements):
        self.elements = elements
    
    def __iter__(self):
        return iter (self.elements)
    
my_list = MyList([1, 2, 3, 4, 5])

for item in my_list:
    print(item)

在此示例中,我们定义了一个名为 MyList 的类,它有一个属性 elements 表示列表的元素。通过重载 __iter__ 方法,我们定义了对象的迭代逻辑,使得对象可以被 for 循环遍历。

__reversed__(self)

__reversed__ 方法定义了该类的实例反向迭代。我们可以通过重载这个方法,自定义对象的反向迭代逻辑。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class MyList:
    def __init__(self, elements):
        self.elements = elements
    
    def __iter__(self):
        return iter (self.elements)
    
    def __reversed__(self):
        return reversed(self.elements)
    
my_list = MyList([1, 2, 3, 4, 5])

for item in reversed(my_list):
    print(item)

在此示例中,我们定义了一个名为 MyList 的类,它有一个属性 elements 表示列表的元素。通过重载 __iter__ 和 __reversed__ 方法,我们定义了对象的迭代逻辑和反向迭代逻辑,使得对象可以被 for 循环正向或反向遍历。

本文由作者按照 CC BY 4.0 进行授权