2013-03-28 21 views
10

In bằng Python không sử dụng __repr__, __unicode__ hoặc __str__ cho lớp con unicode của tôi khi in. Bất kỳ manh mối nào về những gì tôi đang làm sai?In bằng Python không sử dụng __repr__, __unicode__ hoặc __str__ cho lớp con unicode?

Đây là mã của tôi:

Sử dụng Python 2.5.2 (r252: 60.911, 13 Tháng 10 2009, 14:11:59)

>>> class MyUni(unicode): 
...  def __repr__(self): 
...   return "__repr__" 
...  def __unicode__(self): 
...   return unicode("__unicode__") 
...  def __str__(self): 
...   return str("__str__") 
...  
>>> s = MyUni("HI") 
>>> s 
'__repr__' 
>>> print s 
'HI' 

Tôi không chắc chắn nếu điều này là một chính xác xấp xỉ của trên, nhưng chỉ để so sánh:

>>> class MyUni(object): 
...  def __new__(cls, s): 
...   return super(MyUni, cls).__new__(cls) 
...  def __repr__(self): 
...   return "__repr__" 
...  def __unicode__(self): 
...   return unicode("__unicode__") 
...  def __str__(self): 
...   return str("__str__") 
... 
>>> s = MyUni("HI") 
>>> s 
'__repr__' 
>>> print s 
'__str__' 

[EDITED ...] nghe có vẻ như là cách tốt nhất để có được một đối tượng chuỗi isinstance (ví dụ, basestring) và cung cấp quyền kiểm soát unicode lại lần lượt các giá trị, và với một repr unicode là ...

>>> class UserUnicode(str): 
...  def __repr__(self): 
...   return "u'%s'" % super(UserUnicode, self).__str__() 
...  def __str__(self): 
...   return super(UserUnicode, self).__str__() 
...  def __unicode__(self): 
...   return unicode(super(UserUnicode, self).__str__()) 
... 
>>> s = UserUnicode("HI") 
>>> s 
u'HI' 
>>> print s 
'HI' 
>>> len(s) 
2 

Các _ str __ repr _ trên thêm gì để ví dụ này nhưng ý tưởng là để cho thấy một mô hình rõ ràng , để được mở rộng khi cần thiết.

Chỉ cần để chứng minh rằng mô hình này cấp kiểm soát:

>>> class UserUnicode(str): 
...  def __repr__(self): 
...   return "u'%s'" % "__repr__" 
...  def __str__(self): 
...   return "__str__" 
...  def __unicode__(self): 
...   return unicode("__unicode__") 
... 
>>> s = UserUnicode("HI") 
>>> s 
u'__repr__' 
>>> print s 
'__str__' 

Suy nghĩ?

+1

Mã của bạn có thực sự thụt vào như ví dụ đầu tiên không? – GreenMatt

+1

Tôi phải đoán xem câu hỏi của bạn là gì. Nếu tôi hiểu sai, vui lòng cập nhật bài đăng của bạn lên * bao gồm câu hỏi thực tế, rõ ràng *. –

+0

Mặc dù đây là một dấu hiệu tốt đẹp, tôi muốn hỏi tại sao trong h *** bạn muốn phân lớp str hoặc unicode? Ý tôi là, dữ liệu sẽ không thay đổi được, do đó, đối tượng kết quả sẽ hoàn toàn vô dụng. – kay

Trả lời

10

Vấn đề là print không tôn trọng __str__ trên unicode lớp con.

Từ PyFile_WriteObject, được sử dụng bởi print:

int 
PyFile_WriteObject(PyObject *v, PyObject *f, int flags) 
{ 
... 
     if ((flags & Py_PRINT_RAW) && 
    PyUnicode_Check(v) && enc != Py_None) { 
    char *cenc = PyString_AS_STRING(enc); 
    char *errors = fobj->f_errors == Py_None ? 
     "strict" : PyString_AS_STRING(fobj->f_errors); 
    value = PyUnicode_AsEncodedString(v, cenc, errors); 
    if (value == NULL) 
     return -1; 

PyUnicode_Check(v) trả về true nếu loại v 's là unicodehoặc một lớp con. Do đó, mã này viết trực tiếp các đối tượng unicode mà không cần tham khảo __str__.

Lưu ý rằng subclassing str và trọng __str__ tác phẩm như mong đợi:

>>> class mystr(str): 
...  def __str__(self): return "str" 
...  def __repr__(self): return "repr" 
... 
>>> print mystr() 
str 

cũng như kêu gọi str hoặc unicode một cách rõ ràng:

>>> class myuni(unicode): 
...  def __str__(self): return "str" 
...  def __repr__(self): return "repr" 
...  def __unicode__(self): return "unicode" 
... 
>>> print myuni() 

>>> str(myuni()) 
'str' 
>>> unicode(myuni()) 
u'unicode' 

Tôi tin rằng điều này có thể được hiểu như một lỗi trong Python như hiện nay thực hiện.

6

Bạn đang phân lớp unicode.

Nó sẽ không bao giờ gọi __unicode__ vì nó đã là unicode. Chuyện gì xảy ra ở đây thay vì là đối tượng là mã hóa để mã hóa stdout:

>>> s.encode('utf8') 
'HI' 

ngoại trừ việc nó sẽ sử dụng trực tiếp C gọi thay vì phương pháp .encode(). Đây là hành vi mặc định cho print cho các đối tượng unicode.

Gọi print tuyên bố PyFile_WriteObject, lần lượt gọi PyUnicode_AsEncodedString khi xử lý đối tượng unicode. Sau đó, chức năng này sẽ chuyển sang một chức năng mã hóa cho mã hóa hiện tại và chúng sử dụng số Unicode C macros để truy cập trực tiếp vào cấu trúc dữ liệu. Bạn không thể đánh chặn điều này từ Python.

Điều bạn đang tìm kiếm là móc __encode__, tôi đoán vậy. Vì đây là lớp con unicode, print chỉ cần mã hóa, không được chuyển đổi thành unicodelần nữa hoặc cũng không thể chuyển đổi chuỗi thành chuỗi mà không mã hóa rõ ràng. Bạn sẽ phải thực hiện điều này với các nhà phát triển lõi Python, để xem liệu có phải là __encode__ không.

+0

Vì nó không làm điều này cho các lớp con 'str', tôi nghĩ rằng đây là một lỗi Python. Xem câu trả lời của tôi. – nneonneo

+1

@nneonneo: không chắc chắn rằng tôi đồng ý. :-) –

+1

Hm, tại sao nó không phải là một lỗi? Việc xử lý 'str' và' unicode' nên tương đối đồng đều trong Python 2.7. – nneonneo

Các vấn đề liên quan