在Python中,字符串格式化的表示形式
在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的?这样做的确切含义是什么?为什么第二个示例不起作用?
在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()
方法获取对象的字符串表示形式。