【问题标题】:Copying python properties by reference通过引用复制python属性
【发布时间】:2021-04-22 02:48:11
【问题描述】:

我有一个棘手的 Python 结构问题,我无法完全解决。

读取大文件正在从我们的应用程序代码中提取出来并放入它自己的包中。它曾经是一个类,我们称之为Object,将用于访问文件属性,并在我们的Application 周围传递。所以Application 包会调用Object.datetime,但现在必须调用Object.file_handler.datetime。所以我有几个选择:

  1. 对于FileHandler 中的每个属性,在Object 中创建一个仅引用file_handler 对象的属性。所以在Object 做:

    @property
    def datetime(self):
        return self.file_handler.datetime
    

    这看起来很恶心,因为有几十个属性/函数,而且耦合非常紧密。这是我们目前的解决方案。

  2. 想办法自动复制这些函数/属性。比如:

    for property in self.file_handler:
        create self.property with value self.file_handler.property
    

    由于文件的大小,这必须是参考,而不是内存副本。

  3. 浏览应用程序并将对self.object.property 的每个调用替换为self.object.file_handler.property。由于Application 是生产级代码,这是一个很大的问题。它可能会破坏我们一段时间未触及的其他东西(存在单元测试,但它们不是很好)。

  4. 重组一切。 FileHandler 必须在不同的包中,我不想将功能复制/粘贴到 Application 中。我不能让Object 扩展FileHandler 因为Object 在一个实例中代表FileHandler(这让我很头疼;基本上Object 是一个Application 实例并且有多个Applications每个FileHandler 对象运行;FileHandler 对象通过迭代器传递给Application)。我需要Object 因为FileHandler 无法实现Application 功能——它们本来应该是两个类。如果有人对此感兴趣,请告诉我,我可以提供更多的结构细节,但我倾向于使用 hacky 一次性解决方案。

这是一个我似乎无法破解的软件设计问题。我认识到我们的代码很脆弱,并且没有经过精心设计/测试,但它就是这样(其中大部分都比我早,而且这不是软件工程团队 - 主要是数学/物理学人员)。有人有指导吗?选项 2 是我最喜欢的,但我找不到让它工作的代码。

【问题讨论】:

  • "。由于文件的大小,这必须是参考,而不是内存副本。" python 从不隐式创建副本,一切都具有引用语义,并且您必须显式复制对象才能实际创建新对象。在任何情况下,您都可以使用__getattr__ 简单地代理对您的file_handle 对象的属性访问,
  • 我不同意这个问题的结束,这不是多个问题,OP 正在针对他们的问题提出不同的解决方案
  • 对于它的价值,选项 2 是可能的,但我能想到的唯一方法是如此笨拙,以至于它可能不值得。您必须获取self.file_handler 的所有属性名称,然后过滤它们以排除诸如__name____doc____class__ 等魔法属性。我更喜欢Juanpa 的建议。
  • 嘿,您的 getattr 评论帮助我用谷歌搜索了正确的东西,我发现了这个:stackoverflow.com/questions/11637293/…
  • 我无法编辑我上面的评论......不习惯 StackOverflow juanpa 和 wjandrea 是对的,上面是获取所有函数/属性的简单代码。棘手的部分是动态为 Object 创建属性。基本上是在做解决方案 3,但是以自动化的方式。那将是理想的。但我不认为这是可能的......我会继续挖掘。谢谢大家!

标签: python properties attributes


【解决方案1】:

您可以定义Object.__getattr__() 以将属性访问委托给self.file_handler,用于在self 上找不到的属性。

例如:

class FileHandler:
    def __init__(self, filename):
        self.filename = filename

class Object:
    def __init__(self, file_handler):
        self.file_handler = file_handler
        self.x = 'foobar'

    def __getattr__(self, name):
        return getattr(self.file_handler, name)

f = FileHandler('some_file')
obj = Object(f)
print(obj.x)  # -> foobar
print(obj.filename)  # -> some_file
print(obj.y)  # -> AttributeError: 'FileHandler' object has no attribute 'y'

有关更多详细信息,请参阅上面的文档链接。

感谢juanpa.arrivillagaa comment 中提出的建议。


我可能还会添加一些处理以使异常消息更清晰,如下所示:

    def __getattr__(self, name):
        try:
            return getattr(self.file_handler, name)
        except AttributeError:
            # Provide a clearer exception message.
            cls = type(self).__name__
            fh = type(self.file_handler).__name__
            msg = f'Both {cls!r} object and {fh!r} object have no attribute {name!r}'
            raise AttributeError(msg) from None

...

print(obj.y)
# AttributeError: Both 'Object' object and 'FileHandler' object have no attribute 'y'

【讨论】:

    猜你喜欢
    • 2018-07-09
    • 2019-10-20
    • 2017-08-16
    • 1970-01-01
    • 2021-12-03
    • 2012-03-23
    • 1970-01-01
    • 1970-01-01
    • 2012-12-11
    相关资源
    最近更新 更多