Такое поведение неудивительно, если принять во внимание следующее:
Роль (2) была широко освещена в этой теме. (1), вероятно, является фактором, вызывающим удивление, поскольку это поведение не является «интуитивным» при поступлении с других языков.
(1) описано в учебнике Python по классам . При попытке присвоить значение атрибуту класса только для чтения:
... все переменные, найденные вне самой внутренней области, доступны только для чтения ( попытка написать такую переменная просто создаст новую локальную переменную в самой внутренней области, оставив неизмененную идентичную внешнюю переменную неизменной ).
Оглянитесь на исходный пример и рассмотрите приведенные выше пункты:
def foo(a=[]): a.append(5) return a
Здесь
foo
- объект, аa
- атрибутfoo
(доступен вfoo.func_defs[0]
). Посколькуa
является списком,a
является изменяемым и, таким образом, является атрибутом чтения-записиfoo
. Он инициализируется пустым списком, указанным сигнатурой при создании экземпляра функции, и доступен для чтения и записи до тех пор, пока существует функциональный объект.Вызов
foo
без переопределения значения по умолчанию использует значение по умолчанию отfoo.func_defs
. В этом случаеfoo.func_defs[0]
используется дляa
в пределах области кода объекта объекта. Изменения вa
меняютfoo.func_defs[0]
, который является частью объектаfoo
и сохраняется между выполнением кода вfoo
.Теперь сравните это с примером из документации по , эмулируя поведение аргументов по умолчанию других языков , так что значения по умолчанию для функции используются каждый раз, когда функция выполняется:
def foo(a, L=None): if L is None: L = [] L.append(a) return L
Принимая во внимание (1) и (2) , можно понять, почему это выполняет желаемое поведение:
- Когда объект функции
foo
создается,foo.func_defs[0]
установлен наNone
, неизменяемый объект.- Когда функция выполняется с настройками по умолчанию (без функции, заданной для
L
в вызове функции),foo.func_defs[0]
(None
) доступен в локальной области какL
.- После
L = []
присваивание не может преуспеть вfoo.func_defs[0]
, поскольку этот атрибут доступен только для чтения.- Per (1), новая локальная переменная с именем
L
создается в локальной области и используется для остальной части вызова функции.foo.func_defs[0]
, таким образом, остается неизменным для будущих вызововfoo
.
Какими персонажами вы должны и которые вы не должны убежать, действительно зависит от того, с чем вы работаете.
Для PCRE и большинства других так называемых Perl-совместимых ароматов избегайте этих внешних классы символов:
.^$*+?()[{\|
и эти внутренние классы символов:
^-]\
Для POSIX расширенных регулярных выражений (ERE), избегайте этих внешних классов символов (таких же, как PCRE):
.^$*+?()[{\|
Выключение любых других символов является ошибкой с POSIX ERE.
Внутри классов символов обратная косая черта является буквальным символом в регулярных выражениях POSIX. Вы не можете использовать его, чтобы избежать чего-либо. Вы должны использовать «умное размещение», если хотите включить метасимволы класса символов в виде литералов. Поместите ^ в любом месте, кроме как в начале, в начале, а в начале или в конце класса символов, чтобы соответствовать этим буквально, например:
[]^-]
В основных регулярных выражениях POSIX (BRE), это метасимволы, которые вам нужно убежать, чтобы подавить их смысл:
.^$*
Выпуски из круглых скобок и фигурных скобок в BRE дают им особый смысл, который их неописуемые версии имеют в ERE. Некоторые реализации (например, GNU) также придают особое значение другим символам при экранировании, например \? и +. Сброс символа, отличного от. ^ $ * () {}, Как правило, является ошибкой с BRE.
Внутри классов символов BRE следуют тому же правилу, что и ERE.
Если все это делает голова спина, возьмите копию RegexBuddy . На вкладке «Создать» нажмите «Вставить маркер», а затем «Литерал». RegexBuddy добавит экраны при необходимости.
Включает C, C ++, Delphi, EditPad, Java, JavaScript, Perl, PHP (preg), PostgreSQL, PowerGREP, PowerShell, Python, REALbasic, Real Studio, Ruby , TCL, VB.Net, VBScript, wxWidgets, XML Schema, Xojo, XRegExp.PCRE совместимость может различаться
& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; Anywhere: . ^ $ * + - ? ( ) [ ] { } \ |
Включает поддержку awk, ed, egrep, emacs, GNUlib, grep, PHP (ereg), MySQL, Oracle, R, sed.PCRE версии или с помощью расширений
ERE / awk / egrep / emacs
& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; Вне класса символов: . ^ $ * + ? ( ) [ { } \ |
& nbsp; & nbsp; & nbsp; & nbsp; Внутри класса символов: ^ - [ ]
BRE / ed / grep / sed
& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; ; & nbsp; внутри класса символов: ^ - [ ]
& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; g16]
\xFF
] -
требуется только экранирование в классе символов, но я сохранил их в одном списке для простоты "(\")(/)(\\.)"
по сравнению с /(")(\/)(\.)/
в JavaScript) -
или ]
для экранирования вне классов символов. POSIX (BRE / ERE) не имеет escape-символа внутри классов символов. Реджейный вкус в RTL Delphi на самом деле основан на PCRE. Python, Ruby и XML имеют свои собственные вкусы, которые ближе к PCRE, чем к POSIX.
– Jan Goyvaerts
23 February 2017 в 09:05
Действительно, нет. существует около полумиллиона различных синтаксисов регулярных выражений; они, похоже, доходят до Perl, EMACS / GNU и AT & amp; T в целом, но я всегда удивляюсь.
К сожалению, значение таких вещей, как (и \ (меняются между регулярными выражениями стиля Emacs и большинством других стилей). Поэтому, если вы попытаетесь избежать этого, вы можете делать противоположное тому, что вы хотите.
Итак, вам действительно нужно знать, какой стиль вы пытаетесь процитировать.
К сожалению, на самом деле нет установленного набора escape-кодов, поскольку он зависит от языка, который вы используете.
Однако сохранение страницы, такой как Страница регулярных выражений ] или этот Regular Cheatsheet может пройти долгий путь, чтобы помочь вам быстро отфильтровать информацию.
\<
и \>
являются границами слов, что истинно только (AFAIK) в библиотеке регулярных выражений Boost. Но в другом месте он говорит, что <
и >
являются метасимволами и должны быть экранированы (до \<
и \>
), чтобы соответствовать им буквально, что не соответствует ни одному из вкусов
– Alan Moore
7 March 2017 в 06:00
POSIX распознает множество вариантов регулярных выражений - основных регулярных выражений (BRE) и расширенных регулярных выражений (ERE). И даже тогда есть причуды из-за исторических реализаций утилит, стандартизированных POSIX.
Не существует простого правила, когда использовать эту нотацию или даже какую нотацию использовать для данной команды.
Зайдите в книгу Джеффа Фридля , посвященной регулярным выражениям .
Иногда с помощью персонажей, которые вы указали, возможно простое экранирование. Например, использование обратной косой черты для выхода из скобки не будет работать в левой части строки подстановки в sed, а именно
sed -e 's/foo\(bar/something_else/'
. Я просто использую простое определение класса символов вместо , поэтому вышеприведенное выражение становится
sed -e 's/foo[(]bar/something_else/'
, которое я нахожу для большинства реализаций регекса.
BTW Классы символов являются довольно ванильными элементами регулярного выражения, поэтому они, как правило, работают в большинстве ситуаций, когда вы нужны экранированные символы в регулярных выражениях.
Изменить: после комментария ниже, просто подумал, что я бы упомянул о том, что вам также нужно учитывать разницу между автоматами конечного состояния и автоматами не конечного состояния при просмотре поведение оценки regexp.
Возможно, вам захочется взглянуть на «блестящую книгу с шаром», а также на эффективную Perl ( санированную ссылку Amazon ), в частности главу о регулярных выражениях, чтобы получить почувствуйте тогда разницу в типах оценки двигателя regexp.
Не все в мире PCRE!
В любом случае, регулярные выражения настолько неуклюжи по сравнению с SNOBOL ! Теперь это был интересный курс программирования! Наряду с тем, что на Simula .
Ах, радости изучения в UNSW в конце 70-х! (-:
Для PHP, «всегда безопасно предшествовать не-буквенно-цифровому с« \ », чтобы указать, что он обозначает себя». - http://php.net/manual/en/regexp.reference.escape.php .
За исключением случаев, когда это «или».: /
Чтобы избежать переменных шаблона регулярных выражений (или частичных переменных) в PHP, используйте preg_quote ()
/
не является метасимволом в любом из ароматов регулярного выражения, о котором я упоминал, поэтому синтаксис регулярных выражений не требует его ускорения. Когда регулярное выражение цитируется как литерал на языке программирования, тогда правила форматирования строки или регулярного выражения этого языка могут потребовать экранирования/
или"
или'
и могут даже потребовать `\` вдвойне сбежал. – Jan Goyvaerts 7 February 2015 в 00:39