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.
_representationvào thân lớp và return self._representationtrong __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 _representationthà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"
instanceslớ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, reprtrả về một chuỗi có thể được tiêu thụ / thực thi trực tiếp, trong khi đó lại strhữ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ự MCcho 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:
Cmà không có siêu hạng (không class C:)Ccá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ụ.