Najlepsze metody kodowania dla funkcji repr ()?

Ostatnio miałem wiele problemów z __repr__(), format(), i kodowania. czy wyjście __repr__() powinno być zakodowane czy może być ciągiem unicode? czy jest najlepsze kodowanie dla wyniku __repr__() w Pythonie? To, co chcę wypisać, ma znaki inne niż ASCII.

Używam Pythona 2.x i chcą napisać kod, który można łatwo dostosować do Pythona 3. Program używa zatem

# -*- coding: utf-8 -*-
from __future__ import unicode_literals, print_function  # The 'Hello' literal represents a Unicode object

Oto kilka dodatkowych problemów, które mnie trapiły i szukam rozwiązania to je rozwiązuje:

  1. Drukowanie na terminalu UTF-8 powinno zadziałać (mam {[5] } ustawione na UTF-8, ale najlepiej by było, gdyby inne przypadki też zadziałały).
  2. Orurowanie wyjścia do pliku (zakodowanego w UTF-8) powinno zadziałać (w tym przypadku sys.stdout.encoding to None).
  3. mój kod dla wielu __repr__() funkcji ma obecnie wiele return ….encode('utf-8'), a to jest ciężkie. Czy jest coś solidnego i lżejszego?
  4. w niektórych przypadkach mam nawet brzydkie bestie jak return ('<{}>'.format(repr(x).decode('utf-8'))).encode('utf-8'), tzn. reprezentacja obiektów jest zdekodowany, umieszczony w łańcuchu formatującym, a następnie ponownie zakodowany. Chciałbym uniknąć takich zawiłych przekształceń.

Co poleciłbyś zrobić, aby napisać proste __repr__() funkcje, które zachowują się ładnie w odniesieniu do tych pytań kodowania?

Author: Eric Lebigot, 2010-09-02

3 answers

W Python2, __repr__ (i __str__) musi zwracać obiekt string, a nie obiekt unicode. W Python3 sytuacja jest odwrotna, __repr__ i __str__ musi zwracać obiekty unicode, a nie Obiekty byte (née string):

class Foo(object):
    def __repr__(self):
        return u'\N{WHITE SMILING FACE}' 

class Bar(object):
    def __repr__(self):
        return u'\N{WHITE SMILING FACE}'.encode('utf8')

repr(Bar())
# ☺
repr(Foo())
# UnicodeEncodeError: 'ascii' codec can't encode character u'\u263a' in position 0: ordinal not in range(128)

W Python2, tak naprawdę nie masz wyboru. Musisz wybrać kodowanie dla Zwraca wartość __repr__.

Przy okazji, czytałeś printfails wiki? Może nie odpowiadać bezpośrednio twoje inne pytania, ale uznałem to za pomocne w wyjaśnieniu, dlaczego pewne występują błędy.


Podczas stosowania from __future__ import unicode_literals,

'<{}>'.format(repr(x).decode('utf-8'))).encode('utf-8')

Można po prostu zapisać jako

str('<{}>').format(repr(x))

Zakładając, że str koduje do utf-8 w Twoim systemie.

BEZ from __future__ import unicode_literals, wyrażenie można zapisać jako:

'<{}>'.format(repr(x))
 41
Author: unutbu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-09-04 13:00:12

Myślę, że dekorator poradzi sobie z niekompatybilnością w rozsądny sposób. Oto czego używam:

from __future__ import unicode_literals, print_function
import sys

def force_encoded_string_output(func):

    if sys.version_info.major < 3:

        def _func(*args, **kwargs):
            return func(*args, **kwargs).encode(sys.stdout.encoding or 'utf-8')

        return _func

    else:
        return func


class MyDummyClass(object):

    @force_encoded_string_output
    def __repr__(self):
        return 'My Dummy Class! \N{WHITE SMILING FACE}'
 6
Author: Titon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-12-13 03:09:14

Używam funkcji jak poniżej:

def stdout_encode(u, default='UTF8'):
    if sys.stdout.encoding:
        return u.encode(sys.stdout.encoding)
    return u.encode(default)

Wtedy moje __repr__ funkcje wyglądają tak:

def __repr__(self):
    return stdout_encode(u'<MyClass {0} {1}>'.format(self.abcd, self.efgh))
 1
Author: Buttons840,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-17 15:59:59