Primeiro, isso aqui não vai funcionar da maneira que você espera:
op = quest.find('+' or '-' or 'x' or '/')
Vale a pena ver na documentação como funciona o operador or.
Basicamente, na expressão x or y, se x for True (verdadeiro), o valor de x é o resultado da expressão. Se x for False (falso), o valor de y é o resultado da expressão.
Só que segundo este outro trecho da documentação, qualquer string não-vazia é considerada True. E como '+' é uma string não vazia, ela é considerada True e portanto '+' or qualquer_coisa sempre resultará em '+'. Faça o teste:
print('+' or '-' or 'x' or '/') # imprime "+"
Ou seja, você está sempre buscando por '+'.
Sendo assim, para fazer o que você quer, teria que buscar um por um, até encontrar algum: primeiro procura '+', se não encontrar procura '-', e assim por diante, até encontrar um.
Como find retorna -1 se o elemento não for encontrado, você poderia fazer:
quest = input('Digite seu problema:').replace(' ', '')
# lista de operações válidas
operacoes = [ '+', '-', '*', '/' ]
for operacao in operacoes: # procura a operação
indice_op = quest.find(operacao)
if indice_op >= 0: # se foi encontrado
break # já encontrei, não precisa continuar procurando (interrompe o for)
# já pegue os pedaços e transforme em int direto
n1 = int(quest[:indice_op])
n2 = int(quest[indice_op + 1:])
# só faça a operação que foi escolhida (pra que fazer todas as outras?)
# a variável "operacao" usada no for está disponível aqui também, portanto ela já tem o valor da operação encontrada
if operacao == '+':
print(f'{n1} + {n2} = {n1 + n2}')
elif operacao == '-':
print(f'{n1} - {n2} = {n1 - n2}')
elif operacao == '*':
print(f'{n1} * {n2} = {n1 * n2}')
elif operacao == '/':
print(f'{n1} / {n2} = {n1 / n2}')
else:
print('Operação inválida')
Quanto aos slices, eles são start inclusive, end exclusive (o início é incluso, o fim não). E se o início é omitido, ele pega desde o início, e se o fim é omitido, ele vai até o final da string. Portanto, [:4] pega tudo do início até o índice 3, enquanto [3:] pega do índice 3 em diante.
Por isso que para o primeiro número eu posso fazer [:indice_op], pois não pegará a posição em que está a operação. Mas para o segundo eu preciso fazer [indice_op + 1:], para não pegar a operação.
E para os cálculos, prefira usar elif, assim ele só verifica o necessário, e caso entre em uma das condições, nem olha as demais. Fazendo só com if, ele sempre testa todas as condições, o que não é necessário (pois se já entrou em uma, não precisa ver as outras).
Obs: para a multiplicação, você usou x no find e * no if. No código acima eu escolhi usar *.
Outra forma de fazer
Você poderia guardar as operações em um dicionário, mapeando cada uma para uma função específica:
def soma(a, b):
return a + b
def subtracao(a, b):
return a - b
def multiplicacao(a, b):
return a * b
def divisao(a, b):
return a / b
# mapeia cada símbolo para a respectiva função
operacoes = {
'+': soma,
'-': subtracao,
'*': multiplicacao,
'/': divisao
}
quest = input('Digite seu problema:').replace(' ', '')
for operacao, funcao in operacoes.items(): # procura a operação
indice_op = quest.find(operacao)
if indice_op >= 0: # se foi encontrado
# já pegue os pedaços e transforme em int direto
n1 = int(quest[:indice_op])
n2 = int(quest[indice_op + 1:])
print(f'{n1} {operacao} {n2} = {funcao(n1, n2)}')
break # já encontrei, não precisa continuar procurando (interrompe o for)
else:
# se nenhuma operação encontrada, cai aqui
print('operação inválida')
Assim, se a operação existir, você executa a função e já sai do loop. Repare que o else ali é do for e não do if (em Python isso é normal). No caso, se o for não for interrompido por um break, ele cai no else. Ou seja, se não for encontrada uma operação válida, ele cai no else e mostra a mensagem “operação inválida”.