Nowe formatowanie stringów w Pythonie 3.6+, nie ogarniam.

0

Okej, to że mamy w F-Stringach wstawianie wartości w nawiasach klamrowych samo w sobie jest banalne, problem zaczyna się dalej bo im więcej czytam tym mniej rozumiem.
Np żeby dodać precyzje stosuje się zapis "jakaś_liczba:04", co wydaje mi się już od razu debilne bo słowniki też używają przecież dwukropka. Wszystko co próbuje napisać po przeczytaniu dokumentacji i poradników zwyczajnie nie działa, np :

>>> f"{[x:04 for x in range(2)]}"
SyntaxError: invalid syntax
>>> f"{[x for x in range(2)]:04}"
Traceback (most recent call last):
  File "<pyshell#30>", line 1, in <module>
    f"{[x for x in range(2)]:04}"
TypeError: unsupported format string passed to list.__format__

Tracę po mału wiarę w sensowny rozwój pythona, co było nie tak z poprzednią interpolacją stringów? Jak mam wg nowych standardów napisać ekwiwalent np takiej linijki :

    return("{nr:.{precision}f}".format(nr=dict_one.get('nr'),precision=dict_one.get('precision'))).center(dict_one.get('width'))
2

Generalnie, jeśli Chcesz wyświetlić listę z precyzją, to jest to nonsens, w pierwszej linijce interpreter mówi, również, o błędzie składniowym w list comprehension. A jeśli chodzi o precyzję i width, to w f stringach jakoś tak:

>>> a = 10.12345
>>> f"{a:.{4}}"
'10.12'
>>> f"{a:.{5}}"
'10.123'
>>> width = 10
>>> f"{a:{width}.{5}}"
'    10.123'
>>> 
0

Ja bym tylko radził uważać, bo te f-strings to RCE jak zrobicie coś głupiego. Tzn jak ktoś da podokleja tam input usera, bo można z tego stringa wykonywac dowolny kod.

0

Jak mam wg nowych standardów napisać ekwiwalent np takiej linijki :

    return("{nr:.{precision}f}".format(nr=dict_one.get('nr'),precision=dict_one.get('precision'))).center(dict_one.get('width'))
>>> dict_one = {'nr': 42.3, 'precision': 2, 'width': 10}

>>> '{nr:^{width}.{precision}f}'.format_map(dict_one)
'  42.30   '

>>> '{nr:^{width}.{precision}f}'.format(**dict_one)
'  42.30   '

>>> 
3

W jaki to sposób? Pokaż przykład bo to raczej niemożliwe

@anonimowy hold my beer!
Załóżmy że robimy coś w stylu:

equation = input("Podaj dzialanie: ")
print(eval('f"{%s}"' % equation))

(ofc to tylko przykład!)
Niby wszystko spoko, ale co jak ktoś poda ''.__reduce__(42)[0].__globals__['__builtins__']['__import__']('subprocess').check_output('cat /etc/passwd') ? (od razu mówie że takich gadget-chainów jest cała masa, sam mam pod ręką kilkanaście, więc nie ma sensu próbować ich blacklistować :P) :)

1

Ale przecież poprawnie by było print(eval('f"{equation}"')) i już nie zadziała takie kombinowanie. I jeszcze korzystanie z eval przy inpucie od usera :O Ciężko coś takiego zrobić celowo a co dopiero przypadkiem

Właściwie to f-string dodaje Ci dodatkową ochronę bo nawet eval nie zadziała w takim przypadku: eval('f"{equation}"'). A równie dobrze mógłbyś napisać eval(equation) tylko co to ma do f-stringów?

0
Shalom napisał(a):

W jaki to sposób? Pokaż przykład bo to raczej niemożliwe

@anonimowy hold my beer!
Załóżmy że robimy coś w stylu:

equation = input("Podaj dzialanie: ")
print(eval('f"{%s}"' % equation))

(ofc to tylko przykład!)
Niby wszystko spoko, ale co jak ktoś poda ''.__reduce__(42)[0].__globals__['__builtins__']['__import__']('subprocess').check_output('cat /etc/passwd') ? (od razu mówie że takich gadget-chainów jest cała masa, sam mam pod ręką kilkanaście, więc nie ma sensu próbować ich blacklistować :P) :)

Chyba nie rozumiem. Jakim cudem to może zadziałać, skoro cały czas ''.__reduce__(42)[0].__globals__['__builtins__']['__import__']('subprocess').check_output('cat /etc/passwd') będzie traktowane jako string?

screenshot-20190925162124.png

Problemem tu jest użycie eval, a nie f-stringa.

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0