Python 3 ma metodę łańcuchową o nazwie str.isidentifier
Jak uzyskać funkcjonalność Pythona isidentifer() w Pythonie 2.6?
Jak uzyskać podobną funkcjonalność w Pythonie 2.6, bez przepisywania własnego wyrażenia regularnego itp.?
Python 3 ma metodę łańcuchową o nazwie str.isidentifier
Jak uzyskać funkcjonalność Pythona isidentifer() w Pythonie 2.6?
Jak uzyskać podobną funkcjonalność w Pythonie 2.6, bez przepisywania własnego wyrażenia regularnego itp.?
re.match(r'[a-z_]\w*$', s, re.I)
powinien zrobić ładnie. O ile mi wiadomo, nie ma żadnej wbudowanej metody.
W Pythonie < 3.0 jest to całkiem proste, ponieważ nie można mieć znaków Unicode w identyfikatorach. To powinno załatwić pracę:
import re
import keyword
def isidentifier(s):
if s in keyword.kwlist:
return False
return re.match(r'^[a-z_][a-z0-9_]*$', s, re.I) is not None
' [a-z_] 'dla pierwszego znaku. – bobince
Dobrze, ale identyfikatory można rozpoczynać od podkreślenia. –
Tak, myślałem o tym, kiedy to pisałem. –
moduł tokenize definiuje regexp nazwie Nazwa
import re, tokenize, keyword
re.match(tokenize.Name + '$', somestr) and not keyword.iskeyword(somestr)
Do tych celów potrzebujesz '^' + tokenize.Name + '$'. –
Dodaj do wyboru słów zastrzeżonych python, i podoba mi się to. –
@Douglas S.J. De Couto - możesz użyć 'importuj słowo kluczowe',' keyword.iskeyword (astring) ', aby sprawdzić, czy ciąg znaków jest słowem kluczowym, zobacz jego dokumentację [tutaj] (http://docs.python.org/library/keyword.html # keyword.iskeyword). – Abbafei
Dobre odpowiedzi tak daleko. Napisałbym to w ten sposób.
import keyword
import re
def isidentifier(candidate):
"Is the candidate string an identifier in Python 2.x"
is_not_keyword = candidate not in keyword.kwlist
pattern = re.compile(r'^[a-z_][a-z0-9_]*$', re.I)
matches_pattern = bool(pattern.match(candidate))
return is_not_keyword and matches_pattern
Konieczność zezwolenia na duże litery. Powyższe odpowiedzi mają podobny problem. –
@Douglas: do tego służy flaga 're.I'. – SilentGhost
Co Używam:
def is_valid_keyword_arg(k):
"""
Return True if the string k can be used as the name of a valid
Python keyword argument, otherwise return False.
"""
# Don't allow python reserved words as arg names
if k in keyword.kwlist:
return False
return re.match('^' + tokenize.Name + '$', k) is not None
're.match' dopasowuje od początku linii. – SilentGhost
Zdecydowałem się zrobić kolejne pęknięcie na to, ponieważ było kilka dobrych sugestii. Spróbuję je skonsolidować. Poniższe można zapisać jako moduł Pythona i uruchomić bezpośrednio z wiersza poleceń. Po uruchomieniu testuje funkcję, więc jest to poprawne (przynajmniej w takim zakresie, w jakim dokumentacja demonstruje możliwości).
import keyword
import re
import tokenize
def isidentifier(candidate):
"""
Is the candidate string an identifier in Python 2.x
Return true if candidate is an identifier.
Return false if candidate is a string, but not an identifier.
Raises TypeError when candidate is not a string.
>>> isidentifier('foo')
True
>>> isidentifier('print')
False
>>> isidentifier('Print')
True
>>> isidentifier(u'Unicode_type_ok')
True
# unicode symbols are not allowed, though.
>>> isidentifier(u'Unicode_content_\u00a9')
False
>>> isidentifier('not')
False
>>> isidentifier('re')
True
>>> isidentifier(object)
Traceback (most recent call last):
...
TypeError: expected string or buffer
"""
# test if candidate is a keyword
is_not_keyword = candidate not in keyword.kwlist
# create a pattern based on tokenize.Name
pattern_text = '^{tokenize.Name}$'.format(**globals())
# compile the pattern
pattern = re.compile(pattern_text)
# test whether the pattern matches
matches_pattern = bool(pattern.match(candidate))
# return true only if the candidate is not a keyword and the pattern matches
return is_not_keyword and matches_pattern
def test():
import unittest
import doctest
suite = unittest.TestSuite()
suite.addTest(doctest.DocTestSuite())
runner = unittest.TextTestRunner()
runner.run(suite)
if __name__ == '__main__':
test()
Wszystkie rozwiązania proponowane dotychczas nie obsługują Unicode lub pozwolić na numer w pierwszej char jeśli uruchomiony na Pythonie 3.
Edycja: proponowane rozwiązania powinny być używane tylko w Pythonie 2, a na Pythonie 3 należy używać isidentifier
. Oto rozwiązanie, które powinno działać w dowolnym miejscu:
re.match(r'^\w+$', name, re.UNICODE) and not name[0].isdigit()
Zasadniczo, to sprawdza czy coś składa się z (co najmniej 1) znaki (w tym numerów), a następnie sprawdza, że pierwszy znak nie jest liczbą.
Należy zauważyć, że nie działa to w przypadku symboli Unicode, np. ''éllo'' – Almar