Пользовательские типы представления строк форматирования Python / Cython - PullRequest
1 голос
/ 21 декабря 2011

Я знаю, что можно расширить Formatter для предоставления дополнительных типов презентаций, как описано в PEP3101, но это слишком медленно для моих нужд. Мне любопытно, какие еще варианты могут быть для вставки пользовательских типов представления для строк.

В настоящее время единственная другая опция, которая приходит на ум, это проверить {vars} строки, записать тип и индекс презентации, вырезать пользовательский тип презентации, отформатировать, а затем опубликовать результат для моих нужд.

Есть ли другие способы избежать постобработки при использовании скорости форматирования?

1 Ответ

1 голос
/ 22 декабря 2011

Я разработал решение, которое, по-видимому, имеет значительно меньше накладных расходов в cython, хотя то же самое можно было бы сделать в python, и я приведу пример здесь (не уверен в издержках).

Согласно документации по python, объект может реализовать метод __ format__ и получить спецификацию формата. В cython я реализую свой собственный тип uobj, который действует как универсальный для args и kwargs, переданных в str.format. То же самое в python (в качестве общего примера для экранирования <и>) выглядит следующим образом.

class uobj:
    def __init__(self, obj):
        self.obj = obj
    def __format__(self, format_spec):
        if format_spec == 's':
            return str(self.obj)
        else:
            # edit, shoehorning this in for completeness
            # to call an original format spec as should probably
            # happen after you do your own processing, use __format__
            if isinstance(self.obj, (int, float)):
                return self.obj.__format__(format_spec)
                # so then a :.2f spec on uobj(123.456) would work as expected
            return str(self.obj).replace('<', '&lt;').replace('>', '&gt;')
    def __getitem__(self, key):
        return uobj(self.obj[key])

И теперь uobj может хранить пользовательский объект (str или dict в следующем примере), а затем к нему можно получить доступ как

d = uobj({'a': '<b>asdf'})
s = uobj('<span>qwer</span>')
'{0:s} {d[a]}'.format(s, d=d)

# ouputs: '<span>qwer</span>&lt;asdf'

И где приведение к uobj происходит внутри функции fmt для * args и ** kwargs. Здесь еще есть некоторые детали, которые нужно решить, например, я заметил, что ints не удалось разобрать в моих юнит-тестах, и uobj нужно было бы распаковать через * uobj и ** uobj, чтобы конвертировать объекты по требованию, хотя мне может понадобиться разбить это на соответствующие клоны списка и дикт. Тем не менее, это, кажется, лучший путь для меня.

1012 * редактировать *

, кажется, плохо читал о эмуляции типов контейнеров здесь http://docs.python.org/reference/datamodel.html#emulating-container-types

...