Python「內建函數」系列,這篇來介紹 repr(),取得物件的「官方」字串表示。
repr():取得物件的官方字串表示
repr() 回傳物件的「官方」字串表示,通常是可以用 eval() 重新建立該物件的格式。它的目標是「明確」而非「好看」。
語法:repr(obj) # 回傳物件的字串表示基本用法:
# 字串的 repr 會加上引號
print(repr('hello')) # "'hello'"
print(repr("world")) # "'world'"
# 數字的 repr
print(repr(42)) # '42'
print(repr(3.14)) # '3.14'
# 串列的 repr
print(repr([1, 2, 3])) # '[1, 2, 3]'
# 字典的 repr
print(repr({'a': 1})) # "{'a': 1}"repr() vs str():兩種字串表示
str() 是給人看的(可讀性優先),repr() 是給程式看的(明確性優先):
# 字串:最明顯的差異
s = 'hello'
print(str(s)) # hello(沒有引號)
print(repr(s)) # 'hello'(有引號)
# 特殊字元
s2 = 'hello\nworld'
print(str(s2)) # hello
# world(換行了)
print(repr(s2)) # 'hello\nworld'(顯示跳脫字元)
# 日期時間
import datetime
now = datetime.datetime(2024, 1, 15, 10, 30)
print(str(now)) # 2024-01-15 10:30:00(好讀)
print(repr(now)) # datetime.datetime(2024, 1, 15, 10, 30)(可重建)repr() 與除錯
repr() 在除錯時特別有用,因為它會顯示值的真實面貌:
# 看不見的字元
data = 'hello\t\tworld \n'
print(data) # hello world (看不出問題)
print(repr(data)) # 'hello\t\tworld \n'(一目瞭然)
# 分辨空字串和 None
values = ['', None, ' ', 0, False]
for v in values:
print(f'str: {str(v):>10} | repr: {repr(v):>10}')
# str: | repr: ''
# str: None | repr: None
# str: | repr: ' '
# str: 0 | repr: 0
# str: False | repr: False自訂類別的 __repr__
你可以為自己的類別定義 __repr__ 方法,讓 repr() 回傳有意義的資訊:
class Student:
def __init__(self, name, grade):
self.name = name
self.grade = grade
def __repr__(self):
return f"Student('{self.name}', {self.grade})"
def __str__(self):
return f'{self.name}同學({self.grade}年級)'
s = Student('小明', 3)
print(str(s)) # 小明同學(3年級)
print(repr(s)) # Student('小明', 3)
# repr 的結果可以直接用 eval 重建
s2 = eval(repr(s))
print(s2.name) # 小明f-string 中的 !r
在 f-string 中,可以用 !r 快速取得 repr 結果:
name = 'Alice'
data = [1, 2, 3]
# 一般 f-string 用 str()
print(f'名字:{name}') # 名字:Alice
# 加上 !r 用 repr()
print(f'名字:{name!r}') # 名字:'Alice'
print(f'資料:{data!r}') # 資料:[1, 2, 3]
# 除錯時特別好用
value = ' hello '
print(f'value = {value!r}') # value = ' hello '小小綜合例子
來做一個變數檢查器,用 repr() 顯示各種值的真實面貌:
# 變數檢查器
def inspect_value(name, value):
"""詳細檢查一個值"""
print(f'--- {name} ---')
print(f' 型別:{type(value).__name__}')
print(f' str() :{str(value)}')
print(f' repr():{repr(value)}')
# 檢查是否可以用 eval 重建
try:
rebuilt = eval(repr(value))
match = rebuilt == value
print(f' 可重建:是({"相等" if match else "不相等"})')
except:
print(f' 可重建:否')
print()
# 測試各種型別
test_data = {
'字串': 'hello world',
'含跳脫': 'line1\nline2\ttab',
'空字串': '',
'整數': 42,
'浮點數': 3.14159,
'布林': True,
'None': None,
'串列': [1, 'two', 3.0],
'字典': {'key': 'value', 'num': 123},
'元組': (1, 2, 3),
'集合': {1, 2, 3},
}
print('=== 變數檢查器 ===')
print()
for name, value in test_data.items():
inspect_value(name, value)repr() 的重點整理:回傳物件的「官方」字串表示、目標是明確而非好看、在除錯時能看到值的真實面貌、自訂類別可以定義 __repr__ 方法、f-string 中用 !r 快速取得。到這裡「字串與編碼」類別的內建函數就介紹完了!