在Python中,字符串格式化的表示形式

15 浏览
0 Comments

在Python中,字符串格式化的表示形式

我正在迅速学习Python,对于对象的表示形式、字符串形式以及repr方法感到困惑。我使用以下代码调用x = Point(1, 3)并得到以下结果:\n

class Point():
    def __init__(self, x, y):
        '''初始化对象'''
        self.x = x
        self.y = y
    def __repr__(self):
        return "Point({0.x!r}, {0.y!r})".format(self)
    def distance_from_origin(self):
        return math.hypot(self.x, self.y)
>>> x
Point(1, 3)

\n如果!r转换字段用于将变量表示为一个字符串,该字符串可以由Python评估以使用eval()语句创建另一个相同的对象,那么为什么下面的代码不起作用:\n

class Point():
    def __init__(self, x, y):
        '''初始化对象'''
        self.x = x
        self.y = y
    def __repr__(self):
        return "{!r}".format(self)
    def distance_from_origin(self):
        return math.hypot(self.x, self.y)
>>> x
File "C:\...\...\examplepoint.py, line 8, in __repr__
   return "{!r}".format(self)
File "C:\...\...\examplepoint.py, line 8, in __repr__
   return "{!r}".format(self)
File "C:\...\...\examplepoint.py, line 8, in __repr__
   return "{!r}".format(self)
File "C:\...\...\examplepoint.py, line 8, in __repr__
   return "{!r}".format(self)
100行同样的错误
RuntimeError: maximum recursion depth exceeded

\n我以为!r规范会将对象x的类型Point转换为表示形式的字符串,看起来类似于\"Point(1, 3)\"或类似于第一次运行的结果。Python是如何以字符串格式实现这种表示!r的?这样做的确切含义是什么?为什么第二个示例不起作用?

0
0 Comments

在Python中,使用!r来表示将一个对象转化为字符串的repr()形式(也就是调用对象的__repr__方法)。然而,在对象的__repr__方法的定义中要求获取对象的表示形式是没有意义的,因为这样会导致递归调用,而递归调用会在traceback中显示出来。Python并没有要求对象的表示形式必须是可求值的,并且Python也不会为你创建这种表示形式。

原因:

问题的出现是因为在对象的__repr__方法的定义中使用了!r,这会导致递归调用,从而产生递归错误。

解决方法:

要解决这个问题,可以考虑使用!s来代替!r!s会调用str()方法而不是repr()方法,避免了递归调用的问题。

以下是一个示例代码,展示了如何使用!s来避免递归调用的问题:

class Example:
    def __init__(self, name):
        self.name = name
    
    def __repr__(self):
        return f"Example({self.name!s})"

在上面的示例中,我们定义了一个类Example,并在其__repr__方法中使用了!s来获取对象的字符串表示形式。这样就避免了递归调用的问题。

在Python中,使用!r来表示将一个对象转化为字符串的repr()形式是有问题的,因为在对象的__repr__方法中使用!r会导致递归调用。为了避免这个问题,可以使用!s来调用str()方法获取对象的字符串表示形式。

0