英文:
Can you return a __str__ representation of an object within the __repr__ method at recursion level 1?
问题
以下是翻译好的部分:
I am looking for a way to implement a custom __repr__ function in Python, that handles recursion Pythonically, while maintaining readability.
我正在寻找一种在Python中实现自定义__repr__函数的方法,可以以Pythonic方式处理递归,同时保持可读性。
I have two classes (Foo and Bar) that point to each other in their attributes. Of course, simply putting e.g.:
我有两个类(Foo和Bar),它们在它们的属性中互相引用。当然,只是简单地放置如下代码:
Would result in a recursion error. Luckily, there's the @recursive_repr() from reprlib to the rescue. See my implementation below.
这将导致递归错误。幸运的是,有来自reprlib的@recursive_repr()可以帮助解决这个问题。请看下面是我的实现。
However, the custom implementation with fillvalue='...' doesn't improve readability much, in my opinion. Also, this representation of e.g. the foo instance - although I know this isn't required - doesn't make it very reproducible, necessarily.
然而,根据我的看法,使用fillvalue='...'的自定义实现并没有显著提高可读性。此外,对于例如foo实例的表示,尽管我知道这并不是必需的,但并不一定能够很好地复现。
I am looking for an implementation where I can print a string representation of the foo instance, instead of printing the triple dots. I would want an output that'd be something like this: Foo(Bar(my_foo_object)) in which I'd be able to define my_foo_object as the return value of the Foo __str__ method.
我正在寻找一种实现,可以打印foo实例的字符串表示,而不是打印三个点。我希望得到的输出类似于Foo(Bar(my_foo_object)),其中我可以将my_foo_object 定义为Foo的__str__方法的返回值。
Although in the above example this might not make a ton of sense, in my non-MWE it would provide a more intuitive perspective on the objects and their values.
虽然在上面的示例中这可能没有太多意义,但在我的非MWE中,它将提供更直观的对象及其值的视角。
In brief: is it possible to return a __str__ representation of an object within an object's recursive_repr at recursion level 1?
简而言之:在递归级别1中,是否可以在对象的recursive_repr中返回一个对象的__str__表示?
英文:
I am looking for a way to implement a custom __repr__ function in Python, that handles recursion Pythonically, while maintaining readability.
I have two classes (Foo and Bar) that point to each other in their attributes. Of course, simply putting e.g.:
class Foo:
    def __init__(self, bar):
        self.bar = bar
    def __repr__(self):
        return f'Foo({self.bar})'
    @property
    def bar(self):
        return self._bar
    @bar.setter
    def bar(self, bar_instance):
        if bar_instance is not None:
            bar_instance._foo = self
            
        self._bar = bar_instance
class Bar:
    def __init__(self, foo=None):
        self.foo = None
    def __repr__(self):
        return f'Bar({self.foo})'
    @property
    def foo(self):
        return self._foo
    @foo.setter
    def foo(self, foo_instance):
        if foo_instance is not None: 
            foo_instance._bar = self
            
        self._foo = foo_instance
bar = Bar()
foo = Foo(bar)
Would result in a recursion error. Luckily, there's the @recursive_repr() from reprlib to the rescue. See my implementation below.
from reprlib import recursive_repr
class Foo:
    def __init__(self, bar):
        self.bar = bar
    @recursive_repr()
    def __repr__(self):
        return f'Foo({self.bar})'
    @property
    def bar(self):
        return self._bar
    @bar.setter
    def bar(self, bar_instance):
        if bar_instance is not None:
            bar_instance._foo = self
            
        self._bar = bar_instance
class Bar:
    def __init__(self, foo=None):
        self.foo = None
    @recursive_repr()
    def __repr__(self):
        return f'Bar({self.foo})'
    @property
    def foo(self):
        return self._foo
    @foo.setter
    def foo(self, foo_instance):
        if foo_instance is not None: 
            foo_instance._bar = self
            
        self._foo = foo_instance
bar = Bar()
foo = Foo(bar)
However, the custom implementation with fillvalue='...' doesn't improve readability much, in my opinion. Also, this representation of e.g. the foo instance - although I know this isn't required - doesn't make it very reproducible, necessarily.
>>> bar = Bar()
>>> foo = Foo(bar)
>>> foo
... Foo(Bar(...))
I am looking for an implementation where I can print a string representation of the foo instance, instead of printing the triple dots. I would want an output that'd be something like this: Foo(Bar(my_foo_object)) in which I'd be able to define my_foo_object as the return value of the Foo __str__ method.
Although in the above example this might not make a ton of sense, in my non-MWE it would provide a more intuitive perspective on the objects and their values.
In brief: is it possible to return a __str__ representation of an object within an objects recursive_repr at recursion level 1?
答案1
得分: 2
I am looking for an implementation where I can print a string representation of the foo instance, instead of printing the triple dots. I would want an output that'd be something like this: Foo(Bar(my_foo_object)) in which I'd be able to define my_foo_object as the return value of the Foo __str__ method.
你需要为两个类定义自定义的 __str__ 方法:
def __str__(self):
    return "CustomBar"
以及在 __repr__ 中:
def __repr__(self):
    return f'Foo({self.bar})'
在Python中,f-strings 默认使用 __str__ 方法,所以不需要调用 str(self.bar)。在这种情况下,你不需要使用 @reprlib.recursive_repr 修饰你的 __repr__ 函数,因为实际上当自定义 __str__ 函数存在时,不会发生递归。
请注意,你可以重写 Repr.fillvalue 字符串,它默认为省略号 ... 或 reprlib.recursive_repr(fillvalue='somethingCustomHere')。
In brief: is it possible to return a __str__ representation of an object within an object's recursive_repr at recursion level 1?
定义 __str__ 方法会返回字符串表示形式,无需递归调用 __repr__,从而消除了使用 recursive_repr 处理递归的需要。
Hopefully this solves your problem.
英文:
> I am looking for an implementation where I can print a string
> representation of the foo instance, instead of printing the triple
> dots. I would want an output that'd be something like this:
> Foo(Bar(my_foo_object)) in which I'd be able to define my_foo_object
> as the return value of the Foo __str__ method.
You need to define custom __str__ for both classes:
def __str__(self):
    return "CustomBar"
and in __repr__:
def __repr__(self):
    return f'Foo({self.bar})'
fstrings in Python default to __str__ you don't need to call str(self.bar). In this case, you don't need to decorate your __repr__ functions with @reprlib.recursive_repr as no recursion is taking place essentially when custom __str__ functions are present.
Please note that you can override the Repr.fillvalue string which defaults to the ellipsis ... or reprlib.recursive_repr(fillvalue='somethingCustomHere').
> In brief: is it possible to return a __str__ representation of an
> object within an objects recursive_repr at recursion level 1?
Definig __str__ would return the string representation, the string returned by __str__, without necessitating the need of recursive call to __repr__ and thus eliminating the use of recursive_repr to handle recursion.
Hopefully this solves your problem.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论