鱼C论坛

 找回密码
 立即注册
查看: 47|回复: 2

[已解决]魔法方法求助

[复制链接]
发表于 6 天前 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
from pathlib import Path

class FileManager:
    def __init__(self, path="."):
        self.path = Path(path)

    def __getattr__(self, attr):
        if attr in self.__dict__:
            return getattr(self, attr)
        else:
            raise AttributeError(f"{self.__class__.__name__} 对象没有 '{attr}' 属性")

    def __setattr__(self, attr, value):
        if attr == "path":
            object.__setattr__(self, attr, value)
        else:
            setattr(self, attr, value)

    def __delattr__(self, attr):
        if hasattr(self, attr):
            object.__delattr__(self, attr)
        else:
            raise AttributeError(f"{self.__class__.__name__} 对象没有 '{attr}' 属性")

    def browse(self):
        for entry in self.path.iterdir():
            print(entry.name)

    def create(self, file_name):
        file_path = self.path / file_name
        if not file_path.exists():
            file_path.touch()
        else:
            print(f"文件 '{file_name}' 已存在。")

    def delete(self, file_name):
        file_path = self.path / file_name
        if file_path.is_file():
            file_path.unlink()
        elif file_path.is_dir():
            for child in file_path.glob('*'):
                self.delete(child.relative_to(self.path))
            file_path.rmdir()
        else:
            print(f"文件 '{file_name}' 未找到。")

    def rename(self, old_name, new_name):
        old_path = self.path / old_name
        new_path = self.path / new_name
        if old_path.exists() and not new_path.exists():
            old_path.rename(new_path)
        else:
            print(f"错误:'{old_name}' 不存在或 '{new_name}' 已存在。")
请问为什么 def __setattr__(self, attr, value):这段要根据属性是否为‘path’来使用不同的属性设置方法呢?如果是为了防止死循环,而这段却不用分两种情况:
    def __getattr__(self, attr):
        if attr in self.__dict__:
            return getattr(self, attr)
        else:
            raise AttributeError(f"{self.__class__.__name__} 对象没有 '{attr}' 属性")




最佳答案
6 天前
在 `FileManager` 类中,`__setattr__` 方法的设计主要是为了避免调用 `setattr` 时导致的无限递归(死循环)问题。具体来讲,以下是解释:

- 当你设置一个对象的属性时,比如 `self.path = value`,Python 会调用 `__setattr__` 方法。因此,如果在 `__setattr__` 中直接用 `setattr(self, 'path', value)` 设置 `path`,这将导致 `__setattr__` 被无限递归调用。
  
- 为了避免这类递归调用,应该使用 `object.__setattr__(self, attr, value)` 来直接对对象的字典进行操作。这会跳过重新调用 `__setattr__` 方法。

至于 `__getattr__` 方法:

- `__getattr__` 只在试图访问不存在的属性时被调用。也就是说,如果在对象的 `__dict__`(即所有存在的属性)中找不到名字为 `attr` 的属性时,才会调用 `__getattr__`,所以不会出现无限循环。

- 如果 `attr` 在 `self.__dict__` 中,那么它已经是定义过的属性,这时用 `getattr(self, attr)` 来返回属性值,是不会导致无限递归的,因为这不会引起再次调用 `__getattr__`。

总结来说:

1. `__setattr__` 需要特意处理对 `self.path` 的赋值,以避免递归。
2. `__getattr__` 只在访问不存在的属性时被调用,所以不会无限递归。这同样也是为什么 `__setattr__` 不必区分其他属性,而专门对 `path` 进行特别处理。

如果你还有其他问题,可以继续问哦!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 6 天前 | 显示全部楼层    本楼为最佳答案   
在 `FileManager` 类中,`__setattr__` 方法的设计主要是为了避免调用 `setattr` 时导致的无限递归(死循环)问题。具体来讲,以下是解释:

- 当你设置一个对象的属性时,比如 `self.path = value`,Python 会调用 `__setattr__` 方法。因此,如果在 `__setattr__` 中直接用 `setattr(self, 'path', value)` 设置 `path`,这将导致 `__setattr__` 被无限递归调用。
  
- 为了避免这类递归调用,应该使用 `object.__setattr__(self, attr, value)` 来直接对对象的字典进行操作。这会跳过重新调用 `__setattr__` 方法。

至于 `__getattr__` 方法:

- `__getattr__` 只在试图访问不存在的属性时被调用。也就是说,如果在对象的 `__dict__`(即所有存在的属性)中找不到名字为 `attr` 的属性时,才会调用 `__getattr__`,所以不会出现无限循环。

- 如果 `attr` 在 `self.__dict__` 中,那么它已经是定义过的属性,这时用 `getattr(self, attr)` 来返回属性值,是不会导致无限递归的,因为这不会引起再次调用 `__getattr__`。

总结来说:

1. `__setattr__` 需要特意处理对 `self.path` 的赋值,以避免递归。
2. `__getattr__` 只在访问不存在的属性时被调用,所以不会无限递归。这同样也是为什么 `__setattr__` 不必区分其他属性,而专门对 `path` 进行特别处理。

如果你还有其他问题,可以继续问哦!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 6 天前 | 显示全部楼层
不要试图去理解一个错误的代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-1-2 21:16

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表