Что означают обратные линии для интерпретатора python: `num`

Я играю со списком, и я наткнулся на этот маленький фрагмент на другом сайте:

return ''.join([`num` for num in xrange(loop_count)])

Я потратил несколько минут, пытаясь воспроизвести эту функцию (набрав), прежде чем реализовать бит `num`.

Что заключает оператор в этих символах? Из того, что я вижу, это эквивалент str (num). Но когда я его приурочил:

return ''.join([str(num) for num in xrange(10000000)])

Требуется 4.09s, тогда как:

return ''.join([`num` for num in xrange(10000000)])

принимает 2.43s.

Оба дают одинаковые результаты, но один намного медленнее. Что здесь происходит?

EDIT: Странно... repr() дает несколько более медленные результаты, чем `num`. 2,99 против 2,43. Использование Python 2.6 (еще не пробовал 3.0).

Ответ 1

Backticks - устаревший псевдоним для repr(). Не используйте их больше, синтаксис был удален в Python 3.0.

Использование backticks, кажется, быстрее, чем использование repr(num) или num.__repr__() в версии 2.x. Я предполагаю, потому что требуется дополнительный поиск в словаре в глобальном пространстве имен (для repr) или в пространстве имен объектов (для __repr__) соответственно.


Использование модуля dis подтверждает мое предположение:

def f1(a):
    return repr(a)

def f2(a):
    return a.__repr__()

def f3(a):
    return `a`

Разборка показывает:

>>> import dis
>>> dis.dis(f1)
  3           0 LOAD_GLOBAL              0 (repr)
              3 LOAD_FAST                0 (a)
              6 CALL_FUNCTION            1
              9 RETURN_VALUE
>>> dis.dis(f2)
  6           0 LOAD_FAST                0 (a)
              3 LOAD_ATTR                0 (__repr__)
              6 CALL_FUNCTION            0
              9 RETURN_VALUE        
>>> dis.dis(f3)
  9           0 LOAD_FAST                0 (a)
              3 UNARY_CONVERT       
              4 RETURN_VALUE   

f1 включает глобальный поиск для repr, f2 поиска атрибутов для __repr__, тогда как оператор backtick реализован в отдельном коде операции. Поскольку для поиска словаря нет (на английском языке) LOAD_GLOBAL/LOAD_ATTR), а также для вызовов функций (CALL_FUNCTION), backticks быстрее.

Я думаю, что люди Python решили, что отдельная операция низкого уровня для repr() не стоит того, и наличие как repr(), так и обратных ссылок нарушает принцип

"Должен быть один - и желательно только один - простой способ сделать это"

поэтому функция была удалена в Python 3.0.

Ответ 2

Цитата Backtick обычно не нужна и ушла на Python 3.

Для чего это стоит:

''.join(map(repr, xrange(10000000)))

немного быстрее, чем версия backtick для меня. Но беспокоиться об этом, вероятно, является преждевременной оптимизацией.

Ответ 3

Я предполагаю, что num не определяет метод __str__(), поэтому str() должен выполнить второй поиск для __repr__.

Обратные обратки смотрят непосредственно на __repr__. Если это верно, то использование repr() вместо обратных ссылок должно дать вам те же результаты.