Если Вы объявите переменную в функциональных помехах, то его значение не будет сохранено на стопке вызова функции и все еще будет доступно, когда Вы вызовете функцию снова.
, Если Вы объявляете статичную глобальную переменную, ее объем будет ограничен в файле, в котором Вы объявили это. Это немного более безопасно, чем постоянный клиент, глобальный, который может быть считан и изменен всюду по Вашей всей программе.
Final (?) Edit
Ответ, завернутый в функцию, с аннотированным интерактивным сеансом:
>>> import re
>>> def special_match(strg, search=re.compile(r'[^a-z0-9.]').search):
... return not bool(search(strg))
...
>>> special_match("")
True
>>> special_match("az09.")
True
>>> special_match("az09.\n")
False
# The above test case is to catch out any attempt to use re.match()
# with a `$` instead of `\Z` -- see point (6) below.
>>> special_match("az09.#")
False
>>> special_match("az09.X")
False
>>>
Примечание. Ниже в разделе приводится сравнение с использованием re.match () этот ответ. Дальнейшие тайминги показывают, что match () выиграет с гораздо более длинными строками; Если окончательный ответ - True, у match () гораздо больше накладных расходов, чем у search (); это вызывает недоумение (возможно, это стоимость возврата MatchObject вместо None) и может потребовать дальнейшего изучения.
==== Earlier text ====
В [ранее] принятом ответе можно было бы использовать несколько улучшений:
(1) Представление дает видимость результат интерактивного сеанса Python:
reg=re.compile('^[a-z0-9\.]+$')
>>>reg.match('jsdlfjdsf12324..3432jsdflsdf')
True
, но match () не возвращает True
(2) Для использования с match () ^
в начале шаблона будет избыточный, и, кажется, немного медленнее, чем тот же шаблон без ^
(3) Должен автоматически способствовать использованию необработанной строки для любого повторного шаблона
(4) Обратная косая черта перед точкой / точкой избыточно
(5) Медленнее, чем код OP!
prompt>rem OP's version -- NOTE: OP used raw string!
prompt>\python26\python -mtimeit -s"t='jsdlfjdsf12324..3432jsdflsdf';import
re;reg=re.compile(r'[^a-z0-9\.]')" "not bool(reg.search(t))"
1000000 loops, best of 3: 1.43 usec per loop
prompt>rem OP's version w/o backslash
prompt>\python26\python -mtimeit -s"t='jsdlfjdsf12324..3432jsdflsdf';import
re;reg=re.compile(r'[^a-z0-9.]')" "not bool(reg.search(t))"
1000000 loops, best of 3: 1.44 usec per loop
prompt>rem cleaned-up version of accepted answer
prompt>\python26\python -mtimeit -s"t='jsdlfjdsf12324..3432jsdflsdf';import
re;reg=re.compile(r'[a-z0-9.]+\Z')" "bool(reg.match(t))"
100000 loops, best of 3: 2.07 usec per loop
prompt>rem accepted answer
prompt>\python26\python -mtimeit -s"t='jsdlfjdsf12324..3432jsdflsdf';import
re;reg=re.compile('^[a-z0-9\.]+$')" "bool(reg.match(t))"
100000 loops, best of 3: 2.08 usec per loop
(6) Может дать неправильный ответ !!
>>> import re
>>> bool(re.compile('^[a-z0-9\.]+$').match('1234\n'))
True # uh-oh
>>> bool(re.compile('^[a-z0-9\.]+\Z').match('1234\n'))
False
Вот простая реализация на чистом Python. Его следует использовать, когда производительность не критична (включено для будущих сотрудников Google).
import string
allowed = set(string.ascii_lowercase + string.digits + '.')
def check(test_str):
set(test_str) <= allowed
Что касается производительности, итерация, вероятно, будет самым быстрым методом. Регулярные выражения должны проходить через конечный автомат, а решение равенства наборов должно создавать временный набор. Однако вряд ли разница будет иметь большое значение. Если производительность этой функции очень важна, напишите ее как модуль расширения C с оператором switch (который будет скомпилирован в таблицу переходов).
Вот реализация C, который использует операторы if из-за нехватки места. Если вам абсолютно необходима крошечная дополнительная скорость, запишите корпус переключателя. В моих тестах он работает очень хорошо (2 секунды против 9 секунд в тестах с регулярным выражением).
#define PY_SSIZE_T_CLEAN
#include <Python.h>
static PyObject *check(PyObject *self, PyObject *args)
{
const char *s;
Py_ssize_t count, ii;
char c;
if (0 == PyArg_ParseTuple (args, "s#", &s, &count)) {
return NULL;
}
for (ii = 0; ii < count; ii++) {
c = s[ii];
if ((c < '0' && c != '.') || c > 'z') {
Py_RETURN_FALSE;
}
if (c > '9' && c < 'a') {
Py_RETURN_FALSE;
}
}
Py_RETURN_TRUE;
}
PyDoc_STRVAR (DOC, "Fast stringcheck");
static PyMethodDef PROCEDURES[] = {
{"check", (PyCFunction) (check), METH_VARARGS, NULL},
{NULL, NULL}
};
PyMODINIT_FUNC
initstringcheck (void) {
Py_InitModule3 ("stringcheck", PROCEDURES, DOC);
}
Включите его в свой setup.py:[12111 sizes Используйте как:
>>> from stringcheck import check
>>> check("abc")
True
>>> check("ABC")
False
Более простой подход? Еще немного Pythonic?
>>> ok = "0123456789abcdef"
>>> all(c in ok for c in "123456abc")
True
>>> all(c in ok for c in "hello world")
False
Конечно, он не самый эффективный, но вполне читаемый.
РЕДАКТИРОВАТЬ: Изменено регулярное выражение, чтобы исключить AZ
Решение с использованием регулярных выражений является самым быстрым решением на чистом питоне на данный момент
reg=re.compile('^[a-z0-9\.]+$')
>>>reg.match('jsdlfjdsf12324..3432jsdflsdf')
True
>>> timeit.Timer("reg.match('jsdlfjdsf12324..3432jsdflsdf')", "import re; reg=re.compile('^[a-z0-9\.]+$')").timeit()
0.70509696006774902
По сравнению с другими решениями:
>>> timeit.Timer("set('jsdlfjdsf12324..3432jsdflsdf') <= allowed", "import string; allowed = set(string.ascii_lowercase + string.digits + '.')").timeit()
3.2119350433349609
>>> timeit.Timer("all(c in allowed for c in 'jsdlfjdsf12324..3432jsdflsdf')", "import string; allowed = set(string.ascii_lowercase + string.digits + '.')").timeit()
6.7066690921783447
Если вы хотите разрешить пустое strings затем измените его на:
reg=re.compile('^[a-z0-9\.]*$')
>>>reg.match('')
False
По запросу я собираюсь вернуть другую часть ответа. Но обратите внимание, что следующие значения принимают диапазон AZ. Джон привел пример, когда вышеуказанное не работает. Я изменил решение, чтобы преодолеть этот частный случай, используя encode
test_str.replace('.', '').encode('ascii', 'replace').isalnum()
. И оно все еще почти в 3 раза быстрее, чем заданное решение
timeit.Timer("u'ABC\u0131\u0661'.encode('ascii', 'replace').replace('.','').isalnum()", "import string; allowed = set(string.ascii_lowercase + string.digits + '.')").timeit()
1.5719811916351318
. На мой взгляд, использование регулярных выражений - лучшее решение этой проблемы