四时宝库

程序员的知识宝库

19-3-Python-类的常用内置方法(python 类内函数)


Python的类内置方法,也称为魔术方法或特殊方法,允许开发者自定义类的行为,使得对象能够像内置类型一样操作。以下是一些常用的内置方法:

1-__init__(self, ...)

构造函数,在创建实例时自动调用,用于初始化实例属性。

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

2-__new__(cls, ...)

实际上是创建实例对象的方法,通常在需要修改实例创建过程时使用,例如实现单例模式。

2-1-创建实例

class MyClass:
    def __new__(cls, *args, **kwargs):
        print("Creating instance")
        # 调用父类(这里是 'object')的 __new__ 方法来创建实例
        instance = super(MyClass, cls).__new__(cls)
        return instance
    
    def __init__(self, value):
        print("Initializing instance")
        self.value = value

# 创建 MyClass 的实例
obj = MyClass(10)
print(obj.value)  # 输出: 10

2-2-单例模式

class Singleton:
    _instance = None

    def __new__(cls, *args, **kwargs):
        if cls._instance is None:
            print("Creating new instance")
            cls._instance = super(Singleton, cls).__new__(cls, *args, **kwargs)
        else:
            print("Using existing instance")
        return cls._instance

    def __init__(self, value):
        # 注意:由于只创建一次实例,因此 __init__ 每次都会被调用
        # 需要小心处理初始化逻辑避免覆盖之前的值
        self.value = value

# 测试单例模式
singleton1 = Singleton(10)
singleton2 = Singleton(20)

print(singleton1 == singleton2)  # 输出: True,因为singleton1和singleton2指向同一个实例
print(singleton1.value)  # 输出: 20,注意这里值被第二次调用 __init__ 时更新了
print(singleton2.value)  # 输出: 20

3-__del__(self)

它定义了当一个对象即将被销毁时应该执行的操作。这个方法可以用于执行清理工作,比如关闭文件、释放资源等。需要注意的是,由于 Python 的LaJi回收机制依赖引用计数和循环LaJi收集器,__del__ 方法的调用时机并不是完全确定的,特别是在存在循环引用的情况下

import time

class FileHandler:
    def __init__(self, filename):
        print("Opening file")
        self.file = open(filename, 'w')  # 打开文件进行写入
    
    def write(self, message):
        self.file.write(message + '\n')
    
    def __del__(self):
        print("Closing file")
        self.file.close()  # 确保在对象销毁前关闭文件

# 创建 FileHandler 实例并写入一些数据
fh = FileHandler('example.txt')
fh.write("Hello, World!")
fh.write("This is a test.")

# 强制垃圾回收,这将触发 __del__ 方法
time.sleep(2)  # 等待一段时间以确保所有操作完成
del fh  # 显式删除实例,通常不需要这样做,这里为了演示效果

4-__str__(self)

定义了当使用`print()`函数或`str()`函数转换时对象应该如何表示。

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __str__(self):
        return f"Person(name={self.name}, age={self.age})"

p = Person("Alice", 30)
print(p)  # 使用了__str__方法输出更友好的字符串表示形式

输出结果

5-__repr__(self)

定义对象的“官方”字符串表示形式。它主要用于调试和开发过程中提供一个详细的、明确的对象表示。理想情况下,__repr__ 方法应该返回一个字符串,该字符串如果传给 eval() 函数可以重新创建这个对象(尽管在实践中这并不总是可行或实用的)。当没有定义 __str__ 方法时,Python 会使用 __repr__ 方法作为替代。

class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y
    
    def __repr__(self):
        # 返回一个字符串,理论上可以通过 eval() 重建对象
        return f"Point({self.x}, {self.y})"

p = Point(1, 2)
print(p)  # 输出: Point(1, 2)
print(repr(p))  # 输出: Point(1, 2),与 print(p) 相同,因为没有定义 __str__

6-__len__(self)

使对象支持`len()`函数,返回对象的长度。

class MyCollection:
    def __init__(self, data):
        self.data = data
    
    def __len__(self):
        return len(self.data)
coll = MyCollection([1, 2, 3])
print(len(coll))  # 使用了__len__方法

7-__getitem__(self, key)` 和 `__setitem__(self, key, value)

分别允许对象使用索引操作进行获取和设置值,如`obj[key]`。

class MyCollection:
    def __init__(self, data):
        self.data = data
    
    def __getitem__(self, index):
        return self.data[index]
    
    def __setitem__(self, index, value):
        self.data[index] = value

coll = MyCollection([1, 2, 3])
print(coll[0])  # 使用了__getitem__方法
coll[0] = 10  # 使用了__setitem__方法
print(coll[0])

8-__iter__(self)` 和 `__next__(self)

使对象成为可迭代对象。`__iter__`返回迭代器对象,该对象应该实现了`__next__`方法来提供下一个值。

class CountDown:
    def __init__(self, start):
        self.start = start
        self.current = start

    def __iter__(self):
        return self

    def __next__(self):
        if self.current <= 0:
            raise StopIteration
        else:
            self.current -= 1
            return self.current + 1

for num in CountDown(5):
    print(num)

输出结果

9-__contains__(self, item)

支持`in`关键字,检查对象是否包含某个元素。

class MySet:
    def __init__(self, items):
        self.items = set(items)

    def __contains__(self, item):
        return item in self.items


my_set = MySet([1, 2, 3])
print(2 in my_set)  # 使用了__contains__方法
print(4 in my_set)  # 使用了__contains__方法

输出结果

10-__call__(self, ...)

允许一个实例像函数一样被调用。

class ComplexNumber:
    def __init__(self, real, imag):
        self.real = real
        self.imag = imag

    # 加法
    def __add__(self, other):
        return ComplexNumber(self.real + other.real, self.imag + other.imag)

    # 减法
    def __sub__(self, other):
        return ComplexNumber(self.real - other.real, self.imag - other.imag)

    # 乘法
    def __mul__(self, other):
        real = self.real * other.real - self.imag * other.imag
        imag = self.real * other.imag + self.imag * other.real
        return ComplexNumber(real, imag)

    # 除法
    def __truediv__(self, other):
        denom = other.real ** 2 + other.imag ** 2
        real = (self.real * other.real + self.imag * other.imag) / denom
        imag = (self.imag * other.real - self.real * other.imag) / denom
        return ComplexNumber(real, imag)

    def __str__(self):
        return f"{self.real} {'+' if self.imag >= 0 else '-'} {abs(self.imag)}i"


# 测试代码
c1 = ComplexNumber(3, 2)
print(f'c1={c1}')
c2 = ComplexNumber(1, 7)
print(f'c2={c2}')

print(c1 + c2)
print(c1 - c2)
print(c1 * c2)
print(c1 / c2)

输出结果

11-__eq__(self, other)` 等比较方法

如`__eq__`、`__ne__`、`__lt__`、`__le__`、`__gt__`、`__ge__`等,定义了对象之间如何进行比较。

class Number:
    def __init__(self, value):
        self.value = value
    
    def __eq__(self, other):
        return self.value == other.value
    
    def __lt__(self, other):
        return self.value < other.value

n1 = Number(1)
n2 = Number(2)
print(n1 < n2)  # 使用了__lt__方法
print(n1 == n2)  # 使用了__eq__方法

输出结果

12-__add__(self, other)` 等数值运算方法

如`__add__`、`__sub__`、`__mul__`、`__truediv__`等,允许对象参与算术运算。

13-__enter__(self)` 和 `__exit__(self, exc_type, exc_val, exc_tb)

实现上下文管理协议,支持`with`语句。

4-练习题

4-1-实现一个复数类

创建一个名为`ComplexNumber`的类,该类支持以下操作:

- 加法:`c1 + c2`

- 减法:`c1 - c2`

- 乘法:`c1 * c2`

- 除法:`c1 / c2`

- 字符串表示:使用`__str__`或`__repr__`方法使对象打印为易于阅读的形式,如`"3 + 4i"`

class ComplexNumber:
    def __init__(self, real, imag):
        self.real = real
        self.imag = imag
    
    # 加法
    def __add__(self, other):
        return ComplexNumber(self.real + other.real, self.imag + other.imag)
    
    # 减法
    def __sub__(self, other):
        return ComplexNumber(self.real - other.real, self.imag - other.imag)
    
    # 乘法
    def __mul__(self, other):
        real = self.real * other.real - self.imag * other.imag
        imag = self.real * other.imag + self.imag * other.real
        return ComplexNumber(real, imag)
    
    # 除法
    def __truediv__(self, other):
        denom = other.real**2 + other.imag**2
        real = (self.real * other.real + self.imag * other.imag) / denom
        imag = (self.imag * other.real - self.real * other.imag) / denom
        return ComplexNumber(real, imag)
    
    def __str__(self):
        return f"{self.real} {'+' if self.imag >= 0 else '-'} {abs(self.imag)}i"

# 测试代码
c1 = ComplexNumber(3, 2)
c2 = ComplexNumber(1, 7)
print(c1 + c2)
print(c1 - c2)
print(c1 * c2)
print(c1 / c2)

4-2-创建一个可迭代的斐波那契数列生成器

创建一个名为`Fibonacci`的类,该类可以作为一个可迭代对象来生成斐波那契数列。要求实现`__iter__`和`__next__`方法,并且在达到指定的最大项数时停止迭代。

class Fibonacci:
    def __init__(self, max_count):
        self.max_count = max_count
        self.count = 0
        self.a, self.b = 0, 1
    
    def __iter__(self):
        return self
    
    def __next__(self):
        if self.count < self.max_count:
            result = self.a
            self.a, self.b = self.b, self.a + self.b
            self.count += 1
            return result
        else:
            raise StopIteration

# 测试代码
fib = Fibonacci(10)
for num in fib:
    print(num, end=" ")

完成这些练习可以帮助你更好地理解如何使用Python的魔法方法来增强你的类的功能。尝试自己编写代码并测试它们,看看是否能得到预期的结果。如果有任何问题或需要进一步的帮助,请随时提问!

关注小红书 什么IT 943707791

什么IT

发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言
    友情链接