IT俱乐部 Python Python中的魔法函数和魔法属性用法示例

Python中的魔法函数和魔法属性用法示例

前言

Python 中的魔法函数,也被称为特殊方法或双下划线方法,是 Python 中一些特殊命名的函数,它们以双下划线开头和结尾。这些函数定义了对象在特定情况下的行为,例如创建、比较、运算、迭代等。

魔法函数主要是为某些特殊需求而设计的。例如__str__() 和__repr__() 函数用于打印输出对象的信息,__add__() 函数用于定义两个对象相加的行为,__len__() 函数定义当被 len() 调用时的行为等。Python 魔法函数是实现 Python 语法糖的一种方式,提高代码的可读性和可维护性,比如对象相加,大家更习惯 c = a + b 的形式,如果用户使用 a + b 能自动调用 a.__add__(b) 的话,自然要方便很多了,而魔法函数正好有这种功能。

魔法函数

__init__

__init__ 对象初始化函数,在创建实例化对象时自动调用。这个最熟悉的就不多说了。

1
2
3
4
5
class TestClass:
    def __init__(self, name):
        self.name = name
 
obj = TestClass("Alice")

__str__

以用户友好的方式返回对象的字符串表示,使用 str() 时自动调用。

1
2
3
4
5
6
7
8
9
10
class PointClass:
    def __init__(self, x, y):
        self.x = x
        self.y = y
 
    def __str__(self):
        return f"({self.x}, {self.y})"
 
p = PointClass(3, 4)
print(p)  # (3, 4)

__repr__

以开发者友好的方式返回对象的字符串表示,使用 repr() 时自动调用。当使用 print() 函数打印对象时,首先调用的是 __str__ 方法,如果对象没有定义 __str__ 方法,才会调用 __repr__ 方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class PointClass:
    def __init__(self, x, y):
        self.x = x
        self.y = y
 
    def __str__(self):
        return f"({self.x}, {self.y})"
 
    def __repr__(self):
        return f"Point({self.x}, {self.y})"
 
p = PointClass(3, 4)
print(p)  # (3, 4)
print(str(p))  # (3, 4)
print(repr(p))  # Point(3, 4)

__len__

返回对象的长度,使用 len() 自动调用。

1
2
3
4
5
6
7
8
9
class ListClass:
    def __init__(self, items):
        self.items = items
 
    def __len__(self):
        return len(self.items)
 
my_list = ListClass([1, 2, 3, 4, 5])
print(len(my_list))  # 5

__missing__

当尝试访问字典中不存在的键时,如果定义了 __missing__ 方法,它将被调用,而不是抛出 KeyError

1
2
3
4
5
6
7
8
9
10
11
12
class DictClass(dict):
 
    def __missing__(self, key):
        self[key] = "default"
        return "default"
 
my_dict = DictClass({'a': 1, 'b': 2})
print(my_dict['c'])  # default
print(my_dict.keys())  # dict_keys(['a', 'b', 'c'])
 
my_dict = dict({'a': 1, 'b': 2})
print(my_dict['c'])  # KeyError: 'c'

__getitem__

获取对象的指定元素,当使用索引操作符[]来访问对象的元素时自动调用。

1
2
3
4
5
6
7
8
9
class DictClass:
    def __init__(self, items):
        self.items = items
 
    def __getitem__(self, key):
        return self.items.get(key)
 
my_dict = DictClass({'a': 1, 'b': 2})
print(my_dict['a'])  # 1

__setitem__

给对象的指定元素设置值,给对象设定值时自动调用。

1
2
3
4
5
6
7
8
9
10
class DictClass:
    def __init__(self, items):
        self.items = items
 
    def __setitem__(self, key, value):
        self.items[key] = value
 
my_dict = DictClass({'a': 1, 'b': 2})
my_dict['c'] = 3
print(my_dict.items)  # {'a': 1, 'b': 2, 'c': 3}

__delitem__

删除对象指定元素,使用 del 删除对象元素时自动调用。

1
2
3
4
5
6
7
8
9
10
class DictClass:
    def __init__(self, items):
        self.items = items
 
    def __delitem__(self, key):
        del self.items[key]
 
my_dict = DictClass({'a': 1, 'b': 2})
del my_dict['a']
print(my_dict.items)  # {'b': 2}

__contains__

判断对象是否包含指定元素,使用 in 判断时自动调用。

1
2
3
4
5
6
7
8
9
class ListClass:
    def __init__(self, items):
        self.items = items
 
    def __contains__(self, item):
        return item in self.items
 
my_list = ListClass([1, 2, 3, 4, 5])
print(3 in my_list)  # True

__iter__

返回迭代器对象。

1
2
3
4
5
6
7
8
9
10
class ListClass:
    def __init__(self, items):
        self.items = items
 
    def __iter__(self):
        return iter(self.items)
 
my_list = ListClass([1, 2, 3, 4, 5])
for item in my_list:
    print(item)  # 依次输出: 1, 2, 3, 4, 5

__next__

返回迭代器的下一个元素,循环遍历获取对象元素时自动调用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class ListClass:
    def __init__(self, items):
        self.items = items
        self.index = 0
 
    def __iter__(self):
        return self
 
    def __next__(self):
        if self.index >= len(self.items):
            raise StopIteration
        value = self.items[self.index]
        self.index += 1
        return value
 
my_list = ListClass([1, 2, 3, 4, 5])
for item in my_list:
    print(item)  # 依次输出: 1, 2, 3, 4, 5

__eq__

判断两个对象是否相等,两个对象使用 == 判断时自动调用。

1
2
3
4
5
6
7
8
9
10
11
12
13
class PointClass:
    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
 
p1 = PointClass(3, 4)
p2 = PointClass(3, 4)
p3 = PointClass(5, 6)
print(p1 == p2)  # True
print(p1 == p3)  # False

__abs__

输出对象的绝对值。

1
2
3
4
5
6
7
8
9
10
class PointClass:
    def __init__(self, x, y):
        self.x = x
        self.y = y
 
    def __abs__(self):
        return (self.x * self.x + self.y * self.y) ** 0.5
 
p1 = PointClass(3, 4)
print(abs(p1))  # 5.0

__lt__

判断一个对象是否小于另一个对象。

1
2
3
4
5
6
7
class PointClass:
    def __init__(self, x, y):
        self.x = x
        self.y = y
 
    def __lt__(self, other):
        return self.x

 __le__

判断一个对象是否小于或等于另一个对象。

1
2
3
4
5
6
7
class PointClass:
    def __init__(self, x, y):
        self.x = x
        self.y = y
 
    def __le__(self, other):
        return self.x

 __gt__

判断一个对象是否大于另一个对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
class PointClass:
    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
 
p1 = PointClass(3, 4)
p2 = PointClass(3, 4)
p3 = PointClass(1, 2)
print(p1 > p2)  # False
print(p1 > p3)  # True

 __ge__

判断一个对象是否大于或等于另一个对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
class PointClass:
    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
 
p1 = PointClass(3, 4)
p2 = PointClass(3, 4)
p3 = PointClass(1, 2)
print(p1 >= p2)  # True
print(p1 >= p3)  # True

 __add__

定义对象的加法操作,对象之间使用 + 自动调用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class PointClass:
    def __init__(self, x, y):
        self.x = x
        self.y = y
 
    def __add__(self, other):
        return PointClass(self.x + other.x, self.y + other.y)
 
    def __str__(self):
        return f"({self.x}, {self.y})"
 
p1 = PointClass(1, 2)
p2 = PointClass(3, 4)
print(p1 + p2)  # (4, 6)

 __sub__

定义对象的减法操作,对象之间使用 – 自动调用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class PointClass:
    def __init__(self, x, y):
        self.x = x
        self.y = y
 
    def __sub__(self, other):
        return PointClass(self.x - other.x, self.y - other.y)
 
    def __str__(self):
        return f"({self.x}, {self.y})"
 
p1 = PointClass(1, 2)
p2 = PointClass(3, 4)
print(p1 - p2)  # (-2, -2)

 __mul__

定义对象的乘法操作,对象之间使用 * 自动调用,可以根据操作数类型进行对象乘法和数乘。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class PointClass:
    def __init__(self, x, y):
        self.x = x
        self.y = y
 
    def __mul__(self, other):
        if isinstance(other, PointClass):
            return PointClass(self.x * other.x, self.y * other.y)
        elif isinstance(other, int) or isinstance(other, float):
            return PointClass(self.x * other, self.y * other)
        else:
            raise TypeError(f"Unsupported operand type: {type(other)}")
 
    def __str__(self):
        return f"({self.x}, {self.y})"
 
p1 = PointClass(1, 2)
p2 = PointClass(3, 4)
print(p1 * p2)  # (3, 8)
print(p1 * 3# (3, 6)
print(p1 * "t"# TypeError: Unsupported operand type:

__call__

使对象可调用。

1
2
3
4
5
6
7
8
9
10
11
12
class Calculator:
 
    def __init__(self, x, y):
        self.x = x
        self.y = y
 
    def __call__(self):
        return self.x + self.y
 
calc = Calculator(3, 4)
result = calc()
print(result)  # 7
1
2
3
4
5
6
7
class Calculator:
    def __call__(self, a, b):
        return a + b
 
calc = Calculator()
result = calc(3, 4)
print(result)  # 7

__getattr__

在访问对象不存在的属性时调用。

1
2
3
4
5
6
class Person:
    def __getattr__(self, name):
        return f"Attribute '{name}' does not exist."
 
p = Person()
print(p.age)  # Attribute 'age' does not exist.

__setattr__

当设置类实例属性时自动调用。

1
2
3
4
5
6
7
8
class Person:
    def __setattr__(self, name, value):
        print(f"Setting attribute '{name}' to '{value}'")
        super().__setattr__(name, value)
 
p = Person()
p.name = "Alice"  # Setting attribute 'name' to 'Alice'
print(p.name)  # Alice

__delattr__

删除对象属性时自动调用。

1
2
3
4
5
6
7
8
9
10
class Person:
    def __delattr__(self, name):
        print(f"Deleting attribute '{name}'")
        super().__delattr__(name)
 
p = Person()
p.name = "Alice"
print(p.name)  # Alice
del p.name  # Deleting attribute 'name'
print(p.name)  # AttributeError: 'Person' object has no attribute 'name

__enter__

__enter__() 方法用于进入上下文管理器所定义的代码块之前执行的操作。

__exit__

上下文管理器的 __exit__() 方法还有三个参数,即异常类型、异常值和追踪信息。如果在 with 语句块中发生了异常,这些参数会传递给 __exit__() 方法,可以在该方法中进行相关的处理。

__del__

当对象不再被引用时,Python的垃圾回收机制会调用这个方法。

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
class FileHandler:
    def __init__(self, filename):
        self.filename = filename
 
    def __enter__(self):
        print("goto __enter__ open file")
        self.file = open(self.filename, 'w', encoding='utf-8')
        return self.file
 
    def __exit__(self, exc_type, exc_val, exc_tb):
        print("goto __exit__ close file")
        self.file.close()
 
    def __del__(self):
        print("goto __del__ release resource")
 
print("process start")
with FileHandler("./test.txt") as f:
    f.write("hello world!n")
print("process end")
# process start
# goto __enter__ open file
# goto __exit__ close file
# goto __del__ release resource
# process end

魔法属性

__dict__

__dict__ 包含通过 __init__方法初始化的属性和值。

1
2
3
4
5
6
7
8
9
10
class TestClass:
    def __init__(self, name):
        self.name = name
 
    def test(self):
        self.age = 25
 
obj = TestClass("Alice")
print(obj.__dict__)  # {'name': 'Alice'}
# print(TestClass.__dict__)

__slots__

内置类属性__slots__是一个特殊的内置类属性,它可以用于定义类的属性名称的集合。一旦在类中定义了__slots__属性,Python 将限制该类的实例只能拥有__slots__中定义的属性。

1
2
3
4
5
6
7
8
9
10
11
12
class Person:
    __slots__ = ('name', 'age')
 
    def __init__(self, name, age):
        self.name = name
        self.age = age
        self.address = ""  # AttributeError: 'Person' object has no attribute 'address'
 
person = Person("Alice", 30)
print(person.name)  # 输出 "Alice"
print(person.age)  # 输出 30
print(person.__slots__)  # ('name', 'age')

总结 

到此这篇关于Python中的魔法函数和魔法属性的文章就介绍到这了,更多相关Python魔法函数和魔法属性内容请搜索IT俱乐部以前的文章或继续浏览下面的相关文章希望大家以后多多支持IT俱乐部!

本文收集自网络,不代表IT俱乐部立场,转载请注明出处。https://www.2it.club/code/python/14687.html
上一篇
下一篇
联系我们

联系我们

在线咨询: QQ交谈

邮箱: 1120393934@qq.com

工作时间:周一至周五,9:00-17:30,节假日休息

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部