PYTHON_bai_xvan 2024-04-20 11:33 采纳率: 80%
浏览 1
已结题

python __add__方法疑问 入门

python 自定义类实现__add__方法后被视为列表?
导致用不了自定义方法?
源码:

class LimitQueueInitMaxDataValueError(Exception):
    def __init__(self, data: int | float | str):
        self.data = data

    def __str__(self):
        return f"{self.data} is not int"


def max_data_error(data: int | float | str) -> NoReturn:
    raise LimitQueueInitMaxDataValueError(data)
class LimitQueue:
    """限制上限值的队列"""

    def __init__(self, data: list | tuple, max_data: int):
        if type(max_data) is int:
            self.list_ = list(data)
            self.max_data = int(max_data)
        else:
            max_data_error(max_data)

    def __repr__(self):
        return str(self.list_)

    def __str__(self):
        return str(self.list_)

    def __add__(self, other: list | tuple):
        return self.list_ + other

    def __radd__(self, other: list | tuple):
        return other + self.list_

    def __iadd__(self, other: list | tuple):
        self.list_.extend(other)
        self._del_max("<")
        return self.list_

    def _del_max(self, exit_class_str: str):
        if len(self.list_) > self.max_data:
            if exit_class_str == "<":
                while len(self.list_) > self.max_data:
                    del self.list_[0]
            elif exit_class_str == ">":
                while len(self.list_) > self.max_data:
                    del self.list_[-1]

    def set_max_data(self, new_data: int):
        if type(new_data) is int:
            self.max_data = int(new_data)
            self._del_max(">")
        else:
            max_data_error(new_data)

lq1 = LimitQueue([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], max_data=10)

print(type(lq1)) # 输出:<class 'list'> ?
lq1.set_max_data(100) #报错?
  • 写回答

5条回答 默认 最新

  • 专家-赤兔[在线] 全栈领域优质创作者 2024-04-20 11:33
    关注

    引自免费微信小程序:皆我百晓生

    在您提供的代码中,LimitQueue 类确实会有一些意外的行为,因为它继承了 list 的行为,这可能会导致一些混淆。当您创建一个 LimitQueue 实例时,Python 会尝试将它与另一个 listtuple 进行操作,例如使用 + 运算符。这是因为 Python 在处理加法运算时首先检查对象是否实现了 __add__ 方法,如果没有,则会默认调用内置的列表加法。

    要解决这个问题,您可以考虑将 LimitQueue 类从 list 继承改为不继承任何类型,并手动实现 __add____radd____iadd__ 方法所需的逻辑。这样,您的类就不会被误认为是 list 类型。下面是修改后的代码:

    class LimitQueueInitMaxDataValueError(Exception):
        ...
    
    def max_data_error(data):
        ...
    
    class LimitQueue:
        """限制上限值的队列"""
    
        def __init__(self, data=None, max_data=10):
            self.list_ = []
            if data is not None:
                self.extend(data)
            self.max_data = max_data
    
        def __repr__(self):
            return str(self.list_)
    
        def __str__(self):
            return str(self.list_)
    
        def extend(self, other: list | tuple):
            for item in other:
                self.append(item)
    
        def append(self, value):
            if len(self.list_) < self.max_data:
                self.list_.append(value)
            else:
                self._del_max("<")
    
        def __add__(self, other: list | tuple):
            result = LimitQueue()
            result.list_ = self.list_ + [item for item in other if item not in result.list_]
            result.max_data = self.max_data
            return result
    
        def __radd__(self, other: list | tuple):
            result = LimitQueue()
            result.list_ = [item for item in other if item not in result.list_] + self.list_
            result.max_data = self.max_data
            return result
    
        def __iadd__(self, other: list | tuple):
            for item in other:
                self.append(item)
            return self
    
        def _del_max(self, exit_class_str: str):
            ...
    
        def set_max_data(self, new_data):
            ...
    
    lq1 = LimitQueue([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], max_data=10)
    
    print(type(lq1))  # 输出:<class '__main__.LimitQueue'>
    lq1.set_max_data(100)
    

    在这个版本中,我们不再让 LimitQueue 类继承自 list,而是手动实现了添加元素的方法。现在,LimitQueue 对象将不会被误认为是列表,因此可以正确地执行 set_max_data() 方法而不会出错。同时,__add____radd____iadd__ 方法也按照预期工作,不会将两个 LimitQueue 对象简单地合并成一个新的列表。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论 编辑记录
查看更多回答(4条)

报告相同问题?

问题事件

  • 系统已结题 4月28日
  • 已采纳回答 4月20日
  • 创建了问题 4月20日

悬赏问题

  • ¥15 为啥画版图在Run DRC会出现Connect Error?可我Calibre的hostname和计算机的hostname已经设置成一样的了。
  • ¥20 网站后台使用极速模式非常的卡
  • ¥20 Keil uVision5创建project没反应
  • ¥15 mmseqs内存报错
  • ¥15 vika文档如何与obsidian同步
  • ¥15 华为手机相册里面的照片能够替换成自己想要的照片吗?
  • ¥15 陆空双模式无人机飞控设置
  • ¥15 sentaurus lithography
  • ¥100 求抖音ck号 或者提ck教程
  • ¥15 关于#linux#的问题:子进程1等待子进程A、B退出后退出(语言-c语言)