2009-08-20 33 views
182

Có quy ước python khi nào bạn nên triển khai __str__() so với __unicode__(). Tôi đã thấy các lớp ghi đè lên số __unicode__() thường xuyên hơn __str__() nhưng dường như không nhất quán. Có quy tắc cụ thể nào khi thực hiện tốt hơn một quy tắc so với quy tắc khác không? Có cần thiết/thực hành tốt để thực hiện cả hai?Python __str__ so với __unicode__

Trả lời

227

__str__() là phương pháp cũ - nó trả về byte. __unicode__() là phương thức ưa thích mới - nó trả về các ký tự. Các tên có một chút khó hiểu, nhưng trong 2.x chúng tôi đang mắc kẹt với chúng vì lý do tương thích. Nói chung, bạn nên đặt tất cả các chuỗi của bạn định dạng trong __unicode__(), và tạo ra một cuống __str__() phương pháp:

def __str__(self): 
    return unicode(self).encode('utf-8') 

Trong 3.0, str chứa các ký tự, vì vậy các phương pháp tương tự được đặt tên __bytes__()__str__(). Những hành vi như mong đợi.

+1

bạn có nghĩa là tạo cả hai phương thức __unicode__ và __str__ hoặc chỉ giữ chuỗi trong _ (u "") và tạo __string__ (không có phương thức unicode)? – muntu

+9

Có lỗ hổng nào trong việc triển khai chỉ một trong số đó không? Điều gì xảy ra khi bạn chỉ thực hiện '__unicode__' và sau đó làm' str (obj) '? – RickyA

+9

'unicode' tăng một' NameError' trên Python 3, là một mẫu đơn giản hoạt động trên cả 2 và 3? –

9

Với thế giới ngày càng nhỏ hơn, rất có thể là bất kỳ chuỗi nào bạn gặp sẽ chứa Unicode cuối cùng. Vì vậy, đối với bất kỳ ứng dụng mới nào, bạn nên cung cấp ít nhất __unicode__(). Cho dù bạn cũng ghi đè __str__() thì chỉ là vấn đề về hương vị.

19

Nếu tôi không đặc biệt quan tâm đến việc tối ưu hóa vi mô hóa cho một lớp nhất định, tôi luôn thực hiện __unicode__ chỉ vì nó tổng quát hơn. Khi tôi quan tâm đến các vấn đề về hiệu suất phút đó (ngoại lệ, không phải quy tắc), chỉ có __str__ (khi tôi có thể chứng minh sẽ không bao giờ có các ký tự không phải ASCII trong đầu ra được xâu chuỗi) hoặc cả hai (khi cả hai đều có thể), có thể giúp. Tôi nghĩ rằng đó là những nguyên tắc vững chắc, nhưng trong thực tế nó rất phổ biến để BIẾT sẽ không có gì ngoài các ký tự ASCII mà không cần nỗ lực để chứng minh nó (ví dụ: dạng được xâu chuỗi chỉ có chữ số, dấu chấm câu, và có thể là tên ASCII ngắn; -) trong trường hợp nó khá điển hình để chuyển trực tiếp sang phương pháp "chỉ __str__" (nhưng nếu một nhóm lập trình tôi đã làm việc với đề xuất một hướng dẫn địa phương để tránh điều đó, tôi sẽ +1 trên đề xuất, vì nó dễ dàng err trong những vấn đề này và "tối ưu hóa sớm là gốc rễ của tất cả các điều ác trong lập trình" ;-).

+2

Trong python 2.6.2, tôi gần đây đã vấp lên vì trường của một lớp con Ngoại lệ tích hợp đặc biệt cho các kết quả khác nhau với str (e) và unicode (e). str (e) cho đầu ra thân thiện với người dùng; unicode (e) cho đầu ra khác nhau, không thân thiện với người dùng. Đây có phải là hành vi bị lỗi không? Lớp học là UnicodeDecodeError; Tôi đã không đặt tên nó lên phía trước để tránh nhầm lẫn - thực tế là ngoại lệ liên quan đến unicode không liên quan đặc biệt. –

0

Nếu bạn đang làm việc trong cả hai python2 và python3 trong Django, tôi khuyên bạn nên trang trí python_2_unicode_compatible:

Django cung cấp một cách đơn giản để xác định str() và unicode() phương pháp mà làm việc trên Python 2 và 3: bạn phải xác định phương thức trả về str() và áp dụng trang trí python_2_unicode_compatible().

Như đã lưu ý trong các nhận xét trước đó cho một câu trả lời khác, một số phiên bản của future.utils cũng hỗ trợ trình trang trí này. Trên hệ thống của tôi, tôi cần cài đặt một mô-đun tương lai mới hơn cho python2 và cài đặt tương lai cho python3. Sau đó, thì đây là một ví dụ chức năng:

#! /usr/bin/env python 

from future.utils import python_2_unicode_compatible 
from sys import version_info 

@python_2_unicode_compatible 
class SomeClass(): 
    def __str__(self): 
     return "Called __str__" 


if __name__ == "__main__": 
    some_inst = SomeClass() 
    print(some_inst) 
    if (version_info > (3,0)): 
     print("Python 3 does not support unicode()") 
    else: 
     print(unicode(some_inst)) 

Dưới đây là đầu ra ví dụ (nơi venv2/venv3 những trường virtualenv):

~/tmp$ ./venv3/bin/python3 demo_python_2_unicode_compatible.py 
Called __str__ 
Python 3 does not support unicode() 

~/tmp$ ./venv2/bin/python2 demo_python_2_unicode_compatible.py 
Called __str__ 
Called __str__ 
Các vấn đề liên quan