Да, это гарантировано, как описано в документе , который ввел новый алгоритм для вычисления порядка разрешения метода (который является линеаризацией C3 ).
Реализации, которые не используют этот алгоритм для своих mro
, действительно не соответствуют языку python (версия 2.3+). AFAIK вся текущая реализация do использует линеаризацию C3.
Линеаризация C3 удовлетворяет свойствам локального приоритетного упорядочения и монотонности. локальный порядок приоритетов означает, что класс C(B1, ..., Bn)
будет иметь в mro
базовые классы Bi
в том порядке, в котором они были указаны в списке наследования.
Монотонность, вероятно, лучше объясняется примером :
>>> class A(object): pass
>>> class B(object): pass
>>> class C(object): pass
>>> class D(object): pass
>>> class E(object): pass
>>> class K1(A,B,C): pass
>>> class K2(D,B,E): pass
>>> class K3(D,A): pass
>>> class Z(K1,K2,K3): pass
Старая mro для python2.2 (которая не является not монотонной), это линеаризация вышеперечисленных классов:
L[A] = A O
L[B] = B O
L[C] = C O
L[D] = D O
L[E] = E O
L[K1]= K1 A B C O
L[K2]= K2 D B E O
L[K3]= K3 D A O
L[Z] = Z K1 K3 A K2 D B C E O
# in current versions of python (2.3+):
# L[Z] = Z K1 K2 K3 D A B C E O
Здесь вы можете видеть, что в линеаризации Z
класс A
предшествует D
, а в линеаризации K3
он приходит после D
. Монотонность является свойством линеаризации таким образом, что при наследовании таких свопов нет. Если класс X
предшествует классу Y
во всей линеаризации родителей класса, то он также будет предшествовать классу Y
в финальной линеаризации.
Теперь, если мы рассмотрим класс C(B1, ..., Bn)
. По локальному порядку приоритета классы B1, ..., Bn
будут найдены в этом порядке в линеаризации C
. Монотонностью мы не можем найти подклассы Bi
s до самого Bi
. Из этого следует, что линеаризация C
, если она существует, должна начинаться с C
и B1
.
Обратите внимание, что в некоторых случаях вы не можете вычислить линеаризация и питон будут жаловаться, например:
>>> class A(object):pass
...
>>> class B(object, A): pass
...
Traceback (most recent call last):
File "", line 1, in
TypeError: Cannot create a consistent method resolution
order (MRO) for bases object, A
Однако, если вы поменяете классы, можно линеаризовать иерархию:
>>> class B(A, object): pass
...
>>> B.mro()
[, , ]
Если родительские классы не имеют (кроме того, тогда object
очевидно), то ясно, что линеаризация C(B1, ..., Bn)
начнется с линеаризации B1
(кроме object
), затем будет следовать линеаризации B2
и т. д., и это закончится линеаризацией Bn
:
>>> class A(object): pass
...
>>> class B(object): pass
...
>>> class A1(A): pass
...
>>> class A2(A1): pass
...
>>> class B1(B): pass
...
>>> class C(object): pass
...
>>> class C1(C): pass
...
>>> class C2(C1):pass
...
>>> class C3(C2): pass
...
>>> class D(A2, B1, C3): pass
...
>>> D.mro()
[, , , , , , , , , , ]
Вещи начинают странно, когда у вас есть некоторые общие подклассы между Bi
s, и в этом случае либо python находит порядок, который вы ожидаете что не нарушает локальный порядок приоритета и монотонность, или это вызовет ошибку.
R обрабатывает обратную косую черту как escape-значения для символьных констант . (... и, следовательно, регулярные выражения. Следовательно, необходимо наличие двух обратных косых черт при поставке символьного аргумента для шаблона. Первый - это не символ, а второй - символ). Вы можете видеть как они обрабатываются с помощью cat
.
y <- "double quote: \", tab: \t, newline: \n, unicode point: \u20AC"
print(y)
## [1] "double quote: \", tab: \t, newline: \n, unicode point: €"
cat(y)
## double quote: ", tab: , newline:
## , unicode point: €
Дальнейшее чтение: Выключение обратной косой черты с обратным слэшем в R вызывает 2 обратных слэша в строке, а не 1
Чтобы использовать специальные символы в регулярном выражении, простейший метод обычно избегает их с обратным слэшем, но, как отмечалось выше, обратная косая черта должна быть экранирована.
grepl("\\[", "a[b")
## [1] TRUE
Чтобы совместить обратную косую черту, вам нужно удвоить бегство, в результате получится четыре обратных косые черты.
grepl("\\\\", c("a\\b", "a\nb"))
## [1] TRUE FALSE
Пакет rebus
содержит константы для каждого из специальных символов, чтобы сэкономить вам чернильные черты.
library(rebus)
OPEN_BRACKET
## [1] "\\["
BACKSLASH
## [1] "\\\\"
Дополнительные примеры см. в:
?SpecialCharacters
. Ваша проблема может быть решена следующим образом:
library(rebus)
grepl(OPEN_BRACKET, "a[b")
Вы также можете обернуть специальные символы в квадрате b ракеты для формирования класса символов .
grepl("[?]", "a?b")
## [1] TRUE
Два специальных символа имеют особое значение внутри классов символов: \
и ^
.
Обратная косая черта должен быть экранирован, даже если он находится внутри класса символов.
grepl("[\\\\]", c("a\\b", "a\nb"))
## [1] TRUE FALSE
Резерв должен быть только экранирован, если он находится непосредственно после квадратной скобки открытия.
grepl("[ ^]", "a^b") # matches spaces as well.
## [1] TRUE
grepl("[\\^]", "a^b")
## [1] TRUE
rebus
также позволяет вам сформировать класс символов.
char_class("?")
## <regex> [?]
Если вы хотите совместить все знаки препинания, вы можете использовать символ [:punct:]
class.
grepl("[[:punct:]]", c("//", "[", "(", "{", "?", "^", "$"))
## [1] TRUE TRUE TRUE TRUE TRUE TRUE TRUE
stringi
сопоставляет это с общей категорией Unicode для пунктуации, поэтому его поведение немного отличается.
stri_detect_regex(c("//", "[", "(", "{", "?", "^", "$"), "[[:punct:]]")
## [1] TRUE TRUE TRUE TRUE TRUE FALSE FALSE
Вы также можете использовать кросс-платформенную синтаксис для доступа к UGC.
stri_detect_regex(c("//", "[", "(", "{", "?", "^", "$"), "\\p{P}")
## [1] TRUE TRUE TRUE TRUE TRUE FALSE FALSE
Размещение символов между \\Q
и \\E
делает механизм регулярного выражения обрабатывать их буквально, а не как регулярные выражения.
grepl("\\Q.\\E", "a.b")
## [1] TRUE
rebus
позволяет писать литеральные блоки регулярных выражений.
literal(".")
## <regex> \Q.\E
Регулярные выражения не всегда являются ответом. Если вы хотите сопоставить фиксированную строку, вы можете сделать это, например:
grepl("[", "a[b", fixed = TRUE)
stringr::str_detect("a[b", fixed("["))
stringi::stri_detect_fixed("a[b", "[")
Я думаю, что самый простой способ сопоставления символов, таких как
\^$.?*|+()[
, использует классы символов изнутри R. Рассмотрим, как очистить заголовки столбцов от файла данных, которые могут содержать пробелы и пунктуацию characters:
> library(stringr)
> colnames(order_table) <- str_replace_all(colnames(order_table),"[:punct:]|[:space:]","")
Этот подход позволяет нам вводить классы символов в соответствие с символами пунктуации, в дополнение к символам пробелов, что вам обычно нужно было бы избежать с помощью \\
для обнаружения. Вы можете узнать больше о классах символов в этой таблице ниже, и вы также можете ввести ?regexp
, чтобы узнать больше об этом.
https://www.rstudio.com/wp -поперечник / добавления / 2016/09 / RegExCheatsheet.pdf