2012-08-01 13 views
35

Czy są jakieś wady, zastrzeżenia lub ostrzeżenia o złych praktykach dotyczące używania następującego wzoru?Używanie metody locals() i format() dla ciągów znaków: czy są jakieś zastrzeżenia?

def buildString(user, name = 'john', age=22): 
    userId = user.getUserId() 
    return "Name: {name}, age: {age}, userid:{userId}".format(**locals()) 

miałem bardzo powtarzalny ciąg generacji kodu do napisania i kusiło, aby skorzystać z tej, ale coś na temat korzystania locals() sprawia mi nieswojo. Czy jest w tym jakieś niebezpieczeństwo nieoczekiwanego zachowania?

Edit: kontekst

znalazłem się stale pisanie rzeczy jak:

"{name} {age} {userId} {etc}...".format(name=name, age=age, userId=userId, etc=etc) 
+1

Nie widzę w tym nic złego ... – mgilson

+2

Dobra sztuczka! –

+2

Ściśle związane z http://stackoverflow.com/q/1550479/125507 – endolith

Odpowiedz

8

Istnieje oficjalny sposób, aby to zrobić, od Python 3.6.0: formatted string literals.

To działa tak:

f'normal string text {local_variable_name}' 

Np zamiast nich:

"hello %(name)s you are %(age)s years old" % locals() 
"hello {name}s you are {age}s years old".format(**locals()) 

po prostu to zrobić:

f"hello {name}s you are {age}s years old" 

Oto oficjalna przykład:

>>> name = "Fred" 
>>> f"He said his name is {name}." 
'He said his name is Fred.' 
>>> width = 10 
>>> precision = 4 
>>> value = decimal.Decimal("12.34567") 
>>> f"result: {value:{width}.{precision}}" # nested fields 
'result:  12.35' 

referencyjny:

26

Jeśli łańcuch format nie jest dostarczane przez użytkownika, to użycie jest w porządku.

format preferowane jest używanie starego % do zastępowania ciągów znaków.
locals jest wbudowany w Pythonie, a jego zachowanie będzie niezawodne.

Myślę, że locals robi dokładnie to, czego potrzebujesz.
Po prostu nie modyfikuj słownika miejscowych i powiedziałbym, że masz całkiem niezłe rozwiązanie.

Jeśli ciąg formatujący jest dostarczany przez użytkownika, jesteś podatny na ataki różnego rodzaju zła.

+3

Czy nie powinno istnieć zastrzeżenie, że ciąg nigdy nie będzie ** dostarczony przez użytkownika **? To może otworzyć dostęp do zawartości każdej zmiennej lokalnej. –

+0

Proste fotografowanie @ BobStein-VisiBone, zaktualizowałem swoją odpowiedź. –

+0

Wygląda na to, że obciążenie jest bardzo małe przy użyciu locals(), a nie tylko potrzebnych zmiennych, ponieważ masz dodatkowe wywołanie funkcji i konstruujesz większy słownik. Prawdopodobnie jest to nieistotne dla większości aplikacji: widzę różnice około 2% w przypadku szybkiego testu. – Widjet

0

To jest bardzo stary, ale jeśli znajdziesz się za pomocą .format jedno zastrzeżenie jakie napotkano przy przejściu w **locals jest to, że jeśli nie masz tej zmiennej zdefiniowanej w dowolnym miejscu, będzie przerwa . Jawnie stwierdzenie, jakie zmienne są przekazywane, pozwoli uniknąć tego w większości nowoczesnych IDE.

foo = "bar" 
"{foo} and {baz} are pair programming".format(**locals) 
<exception occurs> 
Powiązane problemy