Hãy xem xét lớp này:
class foo(object):
pass
Biểu diễn chuỗi mặc định trông giống như thế này:
>>> str(foo)
"<class '__main__.foo'>"
Làm thế nào tôi có thể làm cho màn hình này hiển thị một chuỗi tùy chỉnh?
Hãy xem xét lớp này:
class foo(object):
pass
Biểu diễn chuỗi mặc định trông giống như thế này:
>>> str(foo)
"<class '__main__.foo'>"
Làm thế nào tôi có thể làm cho màn hình này hiển thị một chuỗi tùy chỉnh?
Câu trả lời:
Thực hiện __str__()
hoặc __repr__()
trong siêu dữ liệu của lớp.
class MC(type):
def __repr__(self):
return 'Wahaha!'
class C(object):
__metaclass__ = MC
print C
Sử dụng __str__
nếu bạn có nghĩa là một chuỗi sắp xếp có thể đọc được, sử dụng __repr__
cho các biểu diễn rõ ràng.
_representation
vào thân lớp và return self._representation
trong __repr__()
phương thức của siêu dữ liệu.
__repr__
để đại diện C
. Một cách khác để có một _representation
thành viên là tạo ra một nhà máy siêu dữ liệu sản xuất một siêu dữ liệu phù hợp __repr__
(điều này có thể tốt nếu bạn sử dụng nhiều thứ này).
class foo(object):
def __str__(self):
return "representation"
def __unicode__(self):
return u"representation"
instances
lớp, không phải cho chính lớp đó.
Nếu bạn phải chọn giữa __repr__
hoặc __str__
chọn cái đầu tiên, như mặc định sẽ thực hiện __str__
các cuộc gọi __repr__
khi nó không được xác định.
Ví dụ về Vector3 tùy chỉnh:
class Vector3(object):
def __init__(self, args):
self.x = args[0]
self.y = args[1]
self.z = args[2]
def __repr__(self):
return "Vector3([{0},{1},{2}])".format(self.x, self.y, self.z)
def __str__(self):
return "x: {0}, y: {1}, z: {2}".format(self.x, self.y, self.z)
Trong ví dụ này, repr
trả về một chuỗi có thể được tiêu thụ / thực thi trực tiếp, trong khi đó lại str
hữu ích hơn như một đầu ra gỡ lỗi.
v = Vector3([1,2,3])
print repr(v) #Vector3([1,2,3])
print str(v) #x:1, y:2, z:3
__repr__
vs __str__
là đúng, nhưng điều này không trả lời câu hỏi thực tế, đó là về các đối tượng lớp, không phải các trường hợp.
Câu trả lời được chấp thuận của Ignacio Vazquez-Abrams là hoàn toàn đúng. Tuy nhiên, đó là từ thế hệ Python 2. Một bản cập nhật cho Python 3 hiện tại sẽ là:
class MC(type):
def __repr__(self):
return 'Wahaha!'
class C(object, metaclass=MC):
pass
print(C)
Nếu bạn muốn mã chạy trên cả Python 2 và Python 3, mô-đun sáu đã bảo vệ bạn:
from __future__ import print_function
from six import with_metaclass
class MC(type):
def __repr__(self):
return 'Wahaha!'
class C(with_metaclass(MC)):
pass
print(C)
Cuối cùng, nếu bạn có một lớp mà bạn muốn có một repr tĩnh tùy chỉnh, cách tiếp cận dựa trên lớp ở trên hoạt động rất tốt. Nhưng nếu bạn có một số, bạn sẽ phải tạo ra một siêu dữ liệu tương tự MC
cho từng loại và điều đó có thể gây mệt mỏi. Trong trường hợp đó, việc lập trình siêu dữ liệu của bạn tiến thêm một bước và tạo một nhà máy siêu dữ liệu giúp mọi thứ sạch sẽ hơn một chút:
from __future__ import print_function
from six import with_metaclass
def custom_class_repr(name):
"""
Factory that returns custom metaclass with a class ``__repr__`` that
returns ``name``.
"""
return type('whatever', (type,), {'__repr__': lambda self: name})
class C(with_metaclass(custom_class_repr('Wahaha!'))): pass
class D(with_metaclass(custom_class_repr('Booyah!'))): pass
class E(with_metaclass(custom_class_repr('Gotcha!'))): pass
print(C, D, E)
in:
Wahaha! Booyah! Gotcha!
Metaprogramming không phải là thứ bạn thường cần hàng ngày nhưng khi bạn cần nó, nó thực sự đạt đến vị trí!
Chỉ cần thêm vào tất cả các câu trả lời tốt, phiên bản của tôi với trang trí:
from __future__ import print_function
import six
def classrep(rep):
def decorate(cls):
class RepMetaclass(type):
def __repr__(self):
return rep
class Decorated(six.with_metaclass(RepMetaclass, cls)):
pass
return Decorated
return decorate
@classrep("Wahaha!")
class C(object):
pass
print(C)
xuất sắc:
Wahaha!
Mặt trái:
C
mà không có siêu hạng (không class C:
)C
các trường hợp sẽ là các trường hợp của một số dẫn xuất lạ, vì vậy có lẽ cũng nên thêm một __repr__
ví dụ.