You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python如何实现链式属性调用以支持嵌套组合名称并返回数据对象?

How to Implement Chainable Attribute Calls in Python

Absolutely, this is totally achievable in Python—great idea for a clean, expressive API! The core issue with your original code is that __getattr__ returns a plain function, which doesn't support further attribute access. Instead, we need to return a chainable object that can both accumulate attribute names and trigger your printer method when called.

Here's a modified version of your code that implements this behavior:

class ChainableCall:
    def __init__(self, parent_printer, current_name):
        self.parent_printer = parent_printer
        self.current_name = current_name

    def __call__(self, *args, **kwargs):
        # When the chain is called (e.g., stack.echo()), trigger the printer method
        return self.parent_printer.printer(self.current_name, *args, **kwargs)

    def __getattr__(self, attr: str):
        # When an attribute is accessed (e.g., stack.echo.fail), extend the name chain
        return ChainableCall(self.parent_printer, f"{self.current_name}.{attr}")

class Printer():
    def __init__(self):
        pass

    def __getattr__(self, attr: str):
        # Return a chainable object starting with the first attribute name
        return ChainableCall(self, attr)

    def printer(self, name, *args, **kwargs):
        print(f'Name:{name}\nArguments:{args}\nKeys:{kwargs}')
        # In your actual project, replace the print with return your custom object here

# Test it out
stack = Printer()
stack.echo('test', special=True)
stack.echo.fail('test', special=True)
stack.echo.fail.pass_('test', special=True)  # Using pass_ since 'pass' is a Python keyword

Key Concepts Explained

Let's break down why this works, since you're still building your Python skills:

  • ChainableCall Helper Class: This is the magic piece. It holds two things: a reference to your original Printer instance, and the accumulated name chain (like "echo" or "echo.fail").
    • __call__: This special method lets the object behave like a function. When you add () to the end of the chain, this method triggers your printer method with the full accumulated name.
    • __getattr__: This catches any attribute access on the ChainableCall object. It creates a new ChainableCall instance with the extended name chain (e.g., "echo" becomes "echo.fail").
  • Modified Printer.__getattr__: Instead of returning a plain function, it returns a ChainableCall instance starting with the first attribute name (like "echo").

Adapting to Your Actual Project

Since you mentioned your real printer-equivalent method returns a custom object, you don't need to change much: just replace the print statement in Printer.printer() with return your_custom_object(...). The ChainableCall.__call__ method will automatically return that object when the chain is called.

Notes for Your Python Journey

This uses two fundamental Python special methods (__getattr__ and __call__) that are super useful for building flexible APIs. Even though you've only been coding Python for 6 months, this is a great project to deepen your understanding of how objects behave in Python—you've already got the right intuition by experimenting with __getattr__!

内容的提问来源于stack exchange,提问作者volitank

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 22:22:48