Rzeczą, która sprawia, że jest to interesujące, jest to, że pierwszy znak identyfikatora jest wyjątkowy. Po pierwszym znaku cyfry od "0" do "9" są ważne dla identyfikatorów, ale nie mogą być pierwszym znakiem.
Oto funkcja, która zwróci prawidłowy identyfikator podany w dowolnym losowym ciągu znaków. Oto, jak to działa:
Najpierw używamy , aby uzyskać jawny iterator na wejściu. Następnie jest pierwsza pętla, która używa iteratora itr
do przeglądania znaków, dopóki nie znajdzie poprawnego pierwszego znaku dla identyfikatora. Następnie wychodzi z tej pętli i uruchamia drugą pętlę, , używając tego samego iteratora (który nazwaliśmy itr
) dla drugiej pętli. Iterator itr
zatrzymuje dla nas swoje miejsce; znaki, które pierwsza pętla wyjęta z iteratora są nadal nieobecne, gdy działa druga pętla.
def gen_valid_identifier(seq):
# get an iterator
itr = iter(seq)
# pull characters until we get a legal one for first in identifer
for ch in itr:
if ch == '_' or ch.isalpha():
yield ch
break
# pull remaining characters and yield legal ones for identifier
for ch in itr:
if ch == '_' or ch.isalpha() or ch.isdigit():
yield ch
def sanitize_identifier(name):
return ''.join(gen_valid_identifier(name))
To jest czysty i Pythoniczny sposób obsługi sekwencji na dwa różne sposoby. Na problem ten prosty, możemy tylko mieć zmienną logiczną wskazującą, czy widzieliśmy jeszcze, czy nie pierwszy znak:
def gen_valid_identifier(seq):
saw_first_char = False
for ch in seq:
if not saw_first_char and (ch == '_' or ch.isalpha()):
saw_first_char = True
yield ch
elif saw_first_char and (ch == '_' or ch.isalpha() or ch.isdigit()):
yield ch
Nie lubię tej wersji prawie tak samo jak w pierwszej wersji. Specjalna obsługa jednego znaku jest teraz zaplątana w cały proces sterowania, a to będzie wolniejsze niż pierwsza wersja, ponieważ musi stale sprawdzać wartość saw_first_char
. Ale w ten sposób musiałbyś kontrolować przepływ w większości języków! Intuicyjny iterator Pythona to fajna funkcja i myślę, że czyni ten kod znacznie lepszym.
Zapętlanie w jawnym iteratorze jest równie szybkie, jak zezwolenie Pythonowi na implicite uzyskanie iteratora dla ciebie, a jawny iterator pozwala nam dzielić pętle, które obsługują różne reguły dla różnych części identyfikatora. Więc jawny iterator daje nam czystszy kod, który działa również szybciej. Wygraj/wygraj.
A powodem odrzucenia głosowania jest ...? To podstawowe pytanie, ale ważne: +1. – EOL
Co robi próba utworzenia klasy o nazwie "Brak" lub "__debug__"? Zgodnie z poniższymi dokumentami, spodziewam się, że podniesie to "SyntaxError": https://docs.python.org/2/library/constants.html – ArtOfWarfare