Aby odpowiedzieć na to pytanie, należy zdefiniować "pełen wdzięku". Warto rozważyć kilka czynników:
- Czy kod jest krótki, łatwy do zapamiętania, łatwy do napisania i nie wymaga objaśnień?
- Czy ponownie wykorzystuje logikę leżącą u podstaw (tj. Przestrzega zasady DRY)?
- Czy implementuje dokładnie tę samą logikę analizowania?
Niestety, formatowanie "%" dla łańcuchów jest zaimplementowane w procedurze C "PyString_Format" w stringojbect.c. Ta procedura nie udostępnia interfejsu API ani haków, które umożliwiają dostęp do przeanalizowanej postaci ciągu formatu. Po prostu buduje wynik podczas analizowania ciągu formatów. Zatem każde rozwiązanie będzie musiało duplikować logikę parsowania z procedury C. Oznacza to, że DRY nie jest przestrzegane i naraża każde rozwiązanie na złamanie, jeśli wprowadzono zmianę w specyfikacji formatowania.
Algorytm parsowania w PyString_Format zawiera spory fragment złożoności, w tym obsługę zagnieżdżonych nawiasów w nazwach kluczy, więc nie można go w pełni zaimplementować za pomocą wyrażeń regularnych ani za pomocą łańcucha "split()".Bez kopiowania kodu C z PyString_Format i konwertowania go na kod Pythona, nie widzę żadnego łatwego sposobu na poprawne wyodrębnienie nazw klawiszy odwzorowania w warunkach wszystkich.
Podsumowując, nie ma "pełnego gracji" sposobu na uzyskanie nazw kluczy mapowania dla łańcucha formatu Python 2.7 "%".
Następujący kod wykorzystuje regularnie ekspresji, aby zapewnić częściowe rozwiązanie obejmuje najczęściej wykorzystywany:
import re
class StringFormattingParser(object):
__matcher = re.compile(r'(?<!%)%\(([^)]+)\)[-# +0-9.hlL]*[diouxXeEfFgGcrs]')
@classmethod
def getKeyNames(klass, formatString):
return klass.__matcher.findall(formatString)
# Demonstration of use with some sample format strings
for value in [
'%(a)s and %(b)s are friends.',
'%%(nomatch)i',
'%%',
'Another %(matched)+4.5f%d%% example',
'(%(should_match(but does not))s',
]:
print StringFormattingParser.getKeyNames(value)
# Note the following prints out "really does match"!
print '%(should_match(but does not))s' % {'should_match(but does not)': 'really does match'}
P.S. DRY = Nie powtarzaj się (https://en.wikipedia.org/wiki/Don%27t_repeat_yourself)
Opisywana metoda działa dobrze. Zwraca ["a", "b"]. Więc czego teraz brakuje? –
@AdiLevin Sposób numer 1 wymaga dodatkowego importu. Sposób numer 2 wymaga innego formatu ciągu. Jestem ciekawy, czy istnieje sposób na uzyskanie tego samego wyniku przy użyciu wewnętrznych metod i właściwości 'string' obiektów lub, być może, niektórych funkcji modułu string. – hackprime
Co uniemożliwia korzystanie z formatu 'format()' do formatowania? Wydaje się, że jest to jeden z tych przypadków, w których jest on po prostu silniejszy. – Joost