Jak mogę wypełnić ciąg Python spacjami?

508

Chcę wypełnić ciąg spacjami. Wiem, że następujące działania są zerowe:

>>> print  "'%06d'"%4
'000004'

Ale co powinienem zrobić, kiedy tego chcę ?:

'hi    '

Oczywiście mogę zmierzyć długość łańcucha i zrobić str+" "*leftover, ale chciałbym najkrótszą drogę.

stożek
źródło
1
Wiem, że może być przestarzałe w przyszłości, ale nadal podoba mi się ta stara dobra metoda: "%-6s" % sdo wyrównania do lewej i wyrównania "%6s" % sdo prawej.
Basj

Odpowiedzi:

698

Możesz to zrobić za pomocą str.ljust(width[, fillchar]):

Zwraca ciąg wyrównany do lewej w ciągu o długości szerokości . Wypełnianie odbywa się przy użyciu określonego fillchar (domyślnie jest to spacja). Oryginalny ciąg znaków jest zwracany, jeśli szerokość jest mniejsza niż len(s).

>>> 'hi'.ljust(10)
'hi        '
Felix Kling
źródło
18
Odpowiedź @simon jest bardziej elastyczna i przydatna podczas formatowania bardziej złożonych ciągów znaków
CoatedMoose
3
lub @abbot, jeśli utknąłeś przy obsłudze starych wersji Pythona
CoatedMoose
1
ljust () jest teraz przestarzałe. Aby
dowiedzieć
Nie ma go w Pythonie 3? Chciałem tylko dodać, że jest tam również rjust i center, które działają w ten sam sposób, ale dla różnych
ustawień
17
ljust (), rjust () zostały wycofane tylko z modułu string. Są dostępne na wbudowanym typie str.
Rohan Grover
372

Aby uzyskać elastyczną metodę, która działa nawet podczas formatowania skomplikowanego łańcucha, prawdopodobnie powinieneś użyć mini-języka formatującego łańcuch , używając jednej z str.format()metod

>>> '{0: <16} StackOverflow!'.format('Hi')  # Python >=2.6
'Hi               StackOverflow!'

z f-łańcuchów

>>> f'{"Hi": <16} StackOverflow!'  # Python >= 3.6
'Hi               StackOverflow!'
Szymon
źródło
11
Co jeśli masz zmienną „16”?
Randy
Też to wymyśliłem. Powinienem to opublikować. Doktorzy mówią, że to powinno działać dla Py2.6, ale moje ustalenia są inne. Działa jednak w wersji Py2.7.
Randy
1
Miałem problemy z tego rodzaju formatowaniem, kiedy używałem akcentów narodowych. Chciałbyś, aby „kra” i „krá” były takie same, ale nie były.
quapka
77
@Randy'{message: <{fill}}'.format(message='Hi', fill='16')
CivFan
19
Nie używaj str.format()dla szablonów zawierających tylko jeden {...}i nic więcej. Wystarczy skorzystać z format()funkcji i oszczędzić sobie parsowania napowietrznych: format('Hi', '<16').
Martijn Pieters
119

Nowa metoda formatowania łańcucha znaków (ish) pozwala robić zabawne rzeczy z zagnieżdżonymi argumentami słów kluczowych. Najprostszy przypadek:

>>> '{message: <16}'.format(message='Hi')
'Hi             '

Jeśli chcesz przekazać 16jako zmienną:

>>> '{message: <{width}}'.format(message='Hi', width=16)
'Hi              '

Jeśli chcesz przekazać zmienne dla całego zestawu i kaboodle :

'{message:{fill}{align}{width}}'.format(
   message='Hi',
   fill=' ',
   align='<',
   width=16,
)

Które wyniki w (zgadłeś):

'Hi              '
CivFan
źródło
Jak poradziłbyś sobie ze zmianą wiadomości? msgs = [„cześć”, „cześć”, „ciao”]
ak_slick
1
@ak_slick Możesz przekazać zmienne zamiast wartości na stałe do funkcji formatu.
CivFan
80

Możesz spróbować:

print "'%-100s'" % 'hi'
opat
źródło
wydrukuj „”% -6s ”„% ”cześć rzeczywiście !!
stożek
8
@simon jak ktoś utknął w systemie python2.5 ta odpowiedź pomogła mi, a nie bezużyteczna odpowiedź +1
sunshinekitty
18
Nie jest już przestarzałe w wersji 3.3+
Seppo Erviälä
3
Podoba mi się ta popularna składnia printf. Umożliwia pisanie złożonych ciągów bez niezliczonych konkatenacji.
Max Tsepkov
4
Dla kompletności, "'%+100s'" % 'hi'będzie działać na umieszczenie spacji po prawej stronie'hi'
Eric Blum
62

Prawidłowym sposobem na to byłoby użycie składni formatu Pythona, jak opisano w oficjalnej dokumentacji

W tym przypadku byłoby to po prostu:
'{:10}'.format('hi')
które dane wyjściowe:
'hi '

Wyjaśnienie:

format_spec ::=  [[fill]align][sign][#][0][width][,][.precision][type]
fill        ::=  <any character>
align       ::=  "<" | ">" | "=" | "^"
sign        ::=  "+" | "-" | " "
width       ::=  integer
precision   ::=  integer
type        ::=  "b" | "c" | "d" | "e" | "E" | "f" | "F" | "g" | "G" | "n" | "o" | "s" | "x" | "X" | "%"

Jest tam prawie wszystko, co musisz wiedzieć ^.

Aktualizacja: od Pythona 3.6 jest jeszcze wygodniejsza z interpolacją ciągów literalnych!

foo = 'foobar'
print(f'{foo:10} is great!')
# foobar     is great!
Granitozaur
źródło
37

Użyj str.ljust():

>>> 'Hi'.ljust(6)
'Hi    '

Należy również rozważyć string.zfill(), str.ljust()a str.center()do formatowania strun. Można je łączyć w łańcuchy i mieć znak „ wypełnienia ”, a zatem:

>>> ('3'.zfill(8) + 'blind'.rjust(8) + 'mice'.ljust(8, '.')).center(40)
'        00000003   blindmice....        '

Te operacje formatowania łańcuchaZaletą jest praca w Pythonie v2 i v3.

Spójrz pydoc strkiedyś: jest tam mnóstwo dobrych rzeczy.

Johnsyweb
źródło
27

Od wersji Python 3.6 możesz to zrobić

>>> strng = 'hi'
>>> f'{strng: <10}'

z dosłowną interpolacją ciągów znaków .

Lub, jeśli twój rozmiar wypełnienia jest w zmiennej, taki jak ten (dzięki @Matt M.!):

>>> to_pad = 10
>>> f'{strng: <{to_pad}}'
WAF
źródło
4
f'{strng: >10}'do wypełniania łańcucha wiodącymi białymi spacjami do długości 10. To magia. I nie jest to dobrze udokumentowane.
Chang Ye
@changye Wierzę, że jest to również domyślne zachowanie f'{strng:10}'.
WAF
17

możesz również wyśrodkować ciąg:

'{0: ^20}'.format('nice')
Remi
źródło
7

Użyj mini formatowania Python 2.7 dla ciągów :

'{0: <8}'.format('123')

To pozostawia wyrównanie i dopełnia do 8 znaków ze znakiem „”.

aodj
źródło
4
@simon już dał tę odpowiedź ... po co publikować duplikat odpowiedzi?
Felix Kling
5
Nie kliknąłem „opublikowano nowe odpowiedzi, kliknij, aby odświeżyć” i dlatego przeoczyłem.
aodj
5

Wystarczy usunąć 0, a zamiast tego doda miejsce:

>>> print  "'%6d'"%4
Amir Mofakhar
źródło
2

Czy nie byłoby bardziej pytoniczne stosowanie krojenia?

Na przykład, aby wstawić ciąg znaków ze spacjami po prawej stronie, aż będzie miał 10 znaków:

>>> x = "string"    
>>> (x + " " * 10)[:10]   
'string    '

Aby uzupełnić go spacjami po lewej stronie, aż będzie miał 15 znaków:

>>> (" " * 15 + x)[-15:]
'         string'

Wymaga to oczywiście wiedzy, jak długo chcesz uzupełniać, ale nie wymaga mierzenia długości łańcucha, od którego zaczynasz.

Zev Chonoles
źródło
9
Nie, nie zrobiłby tego.
Szalony fizyk
1
Czy możesz to rozwinąć? To nie tak, że ci nie wierzę, chcę tylko zrozumieć, dlaczego.
Zev Chonoles
4
Pewnie. Najbardziej pythonicznym sposobem byłoby użycie jednej z wbudowanych funkcji zamiast korzystania z własnego rozwiązania w jak największym stopniu.
Szalony fizyk
@MadPhysicist mówiąc, że krojenie jest mniej pytoniczne, ponieważ powinieneś używać w funkcjach wbudowanych, to tak jakby powiedzieć, że krojenie jest ''.join(reversed(str))bardziej pytoniczne niż str[::-1]i wszyscy wiemy, że to nieprawda.
Nick
@NickA. To nie jest bardzo dobra analogia. Przypadek, którego używasz jako przykładu, jest całkiem poprawny. Jednak (x + " " * 10)[:10]moim zdaniem jest znacznie bardziej skomplikowany niż używanie x.ljust(10).
Szalony fizyk
0

Fajna sztuczka, którą można zastosować zamiast różnych formatów wydruku:

(1) Pad ze spacjami po prawej:

('hi' + '        ')[:8]

(2) Pad z wiodącymi zerami po lewej stronie:

('0000' + str(2))[-4:]
Erik Anderson
źródło
1
Z jakiegoś powodu jest to najśmieszniejsza odpowiedź, ale mi się podoba. Wzdłuż tych linii rozważ również: min_len = 8wtedy ('hi' + ' '*min_len)[:min_len]lub('0'*min_len + str(2))[-min_len]
Poikilos
1
Jeśli chodzi o liczbę, to ('0'*min_len + str(2))[-min_len:]raczej, choć jest to tylko dla zabawy i polecam inne odpowiedzi.
Poikilos
-1

Mógłbyś to zrobić przy użyciu listowania, to dałoby ci wyobrażenie o liczbie spacji i byłby to jeden linijka.

"hello" + " ".join([" " for x in range(1,10)])
output --> 'hello                 '
foobar666
źródło
... a następnie otrzymujesz ciąg o długości 22 (len („hello”) + 17 :() znaków - to nie poszło dobrze. Gdy jesteśmy zabawni, możemy to zrobić s = "hi"; s + (6-len(s)) * " "zamiast tego (jest OK, kiedy wynik jest negatywny). Jednak odpowiedzi, które wykorzystują jakąkolwiek funkcję frameworku, która rozwiązuje konkretny problem, będą łatwiejsze do utrzymania (zobacz inne odpowiedzi)
Poikilos