特殊类变量

在定义类时,Python 提供了一些特殊方法(也称为“魔术方法”或“dunder 方法”,因为它们的名称前后都有双下划线 __, double underscore),这些方法用于为类定义特殊行为。

1. __init__

  • 用于类的初始化。
1
2
3
4
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
  • super().__init__ 用来调用父类的初始化方法、以及属性等
 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
class Parent:
    def __init__(self):
        print("Parent initialized")

class Child(Parent):
    def __init__(self):
        super().__init__()
        print("Child initialized")
        
        
## 词汇表示例
from torchtext.vocab import Vocab #类
from torchtext.vocab import vocab #构造函数(字典)
from torchtext.vocab import build_vocab_from_iterator #构造函数(可迭代对象)

test_obj = build_vocab_from_iterator([["A","B","C"]])
isinstance(test_obj, Vocab)
# True
test_obj.vocab #词汇表内容
Vocab(test_obj.vocab)  #直接基于类构建词表

class GeneVocab(Vocab):
    def __init__(
            self, custom_vocab
    ):
        if not isinstance(custom_vocab, Vocab):
            raise ValueError("Bugs")
        super().__init__(custom_vocab.vocab)
        # 本质就是Vocab(custom_vocab.vocab)

2. __str__

  • 定义对象的“可读”字符串表示,通常用于 print()str() 函数。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
class Person:
    def __init__(self, name):
        self.name = name

    def __str__(self):
        return f"Person named {self.name}"

person = Person("Alice")
print(person)  # 输出:Person named Alice
str(person)    # 输出:Person named Alice     

3. __len__

1
2
3
4
5
6
7
8
9
class MyList:
    def __init__(self, items):
        self.items = items

    def __len__(self):
        return len(self.items)

my_list = MyList([1, 2, 3])
print(len(my_list))  # 输出:3

4. __getitem____setitem__

  • __getitem__:使对象支持下标访问,适用于 obj[key] 语法。
  • __setitem__:设置对象某个下标位置的值。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
class MyList:
    def __init__(self, items):
        self.items = items

    def __getitem__(self, index):
        return self.items[index]
    
    def __setitem__(self, index, value):
        self.items[index] = value

my_list = MyList([1, 2, 3])
print(my_list[0])  # 输出:1

my_list[0] = 10  # 调用 __setitem__
print(my_list[0])  # 输出:10

5. __getattr____setattr__

  • __getattr__:当访问不存在的属性时调用。
1
2
3
4
5
6
7
class MyClass:
    def __getattr__(self, name):
        return f"{name} attribute does not exist"

obj = MyClass()
print(obj.some_attr)  
#some_attr attribute does not exist
  • __setattr__:当设置属性时调用。
1
2
3
4
5
6
7
8
9
class MyClass:
    def __setattr__(self, name, value):
        print(f"Setting {name} to {value}")
        # 调用父类object的__setattr__方法
        super().__setattr__(name, value)

obj = MyClass()
obj.some_attr = 10  
# Setting some_attr to 10

6. __call__

  • 可以让类的实例像函数一样被调用。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
class Adder:
    def __init__(self, increment):
        self.increment = increment

    def __call__(self, x):
        return x + self.increment

# 创建实例
add_five = Adder(5)
# 像函数一样调用
result = add_five(10)
print(result)  # 输出: 15

7. __iter__

  • 返回一个迭代器对象
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
class MyCollection:
    def __init__(self, data):
        self.data = data

    def __iter__(self):
        return iter(self.data)  # 返回一个内置的迭代器

collection = MyCollection([1, 2, 3])
for item in collection:
    print(item)
  • 如果你需要自定义迭代器行为(例如复杂的生成逻辑),则需要实现 __next__ 方法。

特殊内置变量

1. __name__

  • 用于判断模块是被导入还是直接执行。
    • 直接运行py脚本时,__name__ 的值为 “__main__
    • 作为模块导入后,__name__ 的值为模块名

2. __doc__

  • 存储于模块、类或函数的文档字符串(docstring)
1
2
3
4
5
def example():
    """This is a docstring."""
    pass

print(example.__doc__)  # 输出: This is a docstring.

3. __file__

  • 在模块定义内部,表示模块的文件路径。

4. __dict__

  • 存储对象的属性字典。
1
2
3
4
5
6
class MyClass:
    def __init__(self):
        self.attr = 42

obj = MyClass()
print(obj.__dict__)  # 输出: {'attr': 42}