Вы неправильно понимаете, как работают булевы выражения; они не работают как английское предложение и предполагают, что вы говорите о том же сравнении для всех имен здесь. Вы ищете:
if x == 1 or y == 1 or z == 1:
x
и y
иначе оцениваются самостоятельно (False
, если 0
, True
в противном случае).
Вы можете сократить это, используя тест сдерживания против кортежа :
if 1 in (x, y, z):
или еще лучше:
if 1 in {x, y, z}:
с помощью a set
, чтобы воспользоваться тестом на членство в постоянной стоимости (in
занимает фиксированное количество времени, независимо от того, какой левый операнд есть).
Когда вы используете or
, питон видит каждая сторона оператора в виде отдельных выражений. Выражение x or y == 1
рассматривается как первый булевой тест для x
, тогда, если это False, проверяется выражение y == 1
.
Это связано с приоритетом оператора . Оператор or
имеет более низкий приоритет, чем тест ==
, поэтому последний сначала оценивается .
Однако, даже если это были не случай, а выражение x or y or z == 1
было фактически интерпретировано как (x or y or z) == 1
, но это все равно не будет делать то, что вы ожидаете от него.
x or y or z
будет оценивать первый аргумент, который является «правдивым», например. не False
, числовое 0 или пустое (см. логические выражения для получения подробной информации о том, что Python считает ложным в булевом контексте).
Итак, для значений x = 2; y = 1; z = 0
, x or y or z
будет разрешено 2
, потому что это первое истинное значение в аргументах. Тогда 2 == 1
будет False
, хотя y == 1
будет True
.
То же самое относится к обратному; тестирование нескольких значений по одной переменной; x == 1 or 2 or 3
потерпит неудачу по тем же причинам. Используйте x == 1 or x == 2 or x == 3
или x in {1, 2, 3}
.
Вы можете заменить неживое подстановочное соответствие для символов в круглых скобках с помощью функции, которая разделяет совпадение по пробелам и присоединяется к ней.
>>> import re
>>> res = '(321, 3)-(m-5, 5) -(31,1)'
>>> re.sub(r'\(.*?\)', lambda x: ''.join(x.group(0).split()), res)
'(321,3)-(m-5,5) -(31,1)'
Вы можете преобразовать строку в список, пройти каждую букву и подсчитать, если вы находитесь в скобках или нет. В ToRemove вы собираете позиции пробелов, которые затем удаляете из списка. Затем вы конвертируете список обратно в строку ...
res = '(321, 3)-(m-5, 5) -(31,1)'
r = list(res)
insideBracket = 0
toRemove = []
for pos,letter in enumerate(r):
if letter == '(':
insideBracket += 1
elif letter == ')':
insideBracket -= 1
if insideBracket > 0:
if letter == ' ':
toRemove.append(pos)
for t in toRemove[::-1]:
r.pop(t)
result = ''.join(r)
print(result)
Я думаю, что регулярные выражения недостаточно мощны, чтобы делать то, что вы хотите здесь; вы хотите удалить все пробелы, найденные между символами скобок. Проблема в том, что решение этого для общего случая означает, что вы выполняете контекстно-зависимое соответствие строки, а регулярные выражения в основном нечувствительны к контексту и поэтому не могут выполнять вашу работу. Есть lookaheads и lookbehinds , которые могут ограничивать совпадения с конкретными контекстами, но они не будут решать вашу проблему в общем случае:
Содержащийся шаблон должен соответствовать только строки некоторой фиксированной длины, что означает, что
blockquote>abc
илиa|b
разрешены, ноa*
иa{3,4}
- нет. Ссылки группы не поддерживаются, даже если они соответствуют строкам некоторой фиксированной длины.Из-за этого я сначала сопоставлял бы группы скобок:
>>> re.split(r'(\([^)]*\))', res) ['', '(321, 3)', '-', '(m-5, 5)', ' -', '(31,1)', '']
, а затем удалите пробелы из них на втором шаге перед тем, как
join
все вернется в одну строку:>>> g = re.split(r'(\([^)]*\))', res) >>> g[1::2] = [re.sub(r'\s*', '', x) for x in g[1::2]] >>> ''.join(g) '(321,3)-(m-5,5) -(31,1)'