en primer lugar, tratar de evitar el código como este:.
if Action():
lots of code
return True
return False
Dale la vuelta, por lo que la mayor parte del código no está anidado. Esto nos da:
def check(isbn):
check_digit = int(isbn[-1])
match = re.search(r'(\d)-(\d{3})-(\d{5})', isbn[:-1])
if not match:
return False
digits = match.group(1) + match.group(2) + match.group(3)
result = 0
for i, digit in enumerate(digits):
result += (i + 1) * int(digit)
return True if (result % 11) == check_digit else False
Hay algunos errores en el código:
- Si el dígito de control no es un entero, esto elevará ValueError en lugar de devolver Falso: "0-123-12345 -Q ".
- Si el dígito de verificación es 10 ("X"), esto aumentará ValueError en lugar de devolver True.
- Esto supone que el ISBN se agrupa siempre como "1-123-12345-1". Ese no es el caso; Los ISBN se agrupan arbitrariamente. Por ejemplo, la agrupación "12-12345-12-1" es válida. Ver http://www.isbn.org/standards/home/isbn/international/html/usm4.htm.
- Esto supone que el ISBN está agrupado por guiones. Los espacios también son válidos.
- No comprueba que no haya caracteres adicionales; '0-123-4567819' devuelve verdadero, ignorando el 1 adicional al final.
Así que, simplifiquemos esto. Primero, elimine todos los espacios y guiones, y asegúrese de que la expresión regular coincida con toda la línea al reforzarla en '^ ... $'. Eso asegura que rechaza cadenas demasiado largas.
def check(isbn):
isbn = isbn.replace("-", "").replace(" ", "");
check_digit = int(isbn[-1])
match = re.search(r'^(\d{9})$', isbn[:-1])
if not match:
return False
digits = match.group(1)
result = 0
for i, digit in enumerate(digits):
result += (i + 1) * int(digit)
return True if (result % 11) == check_digit else False
A continuación, solucionemos el problema del dígito de control "X". Haga coincidir el dígito de control en la expresión regular también, de modo que toda la cadena sea validada por la expresión regular, luego convierta el dígito de verificación correctamente.
def check(isbn):
isbn = isbn.replace("-", "").replace(" ", "").upper();
match = re.search(r'^(\d{9})(\d|X)$', isbn)
if not match:
return False
digits = match.group(1)
check_digit = 10 if match.group(2) == 'X' else int(match.group(2))
result = 0
for i, digit in enumerate(digits):
result += (i + 1) * int(digit)
return True if (result % 11) == check_digit else False
Por último, utilizando una expresión generador y max
es una forma más idiomática de hacer el cálculo final en Python, y la final condicional puede ser simplificado.
def check(isbn):
isbn = isbn.replace("-", "").replace(" ", "").upper();
match = re.search(r'^(\d{9})(\d|X)$', isbn)
if not match:
return False
digits = match.group(1)
check_digit = 10 if match.group(2) == 'X' else int(match.group(2))
result = sum((i + 1) * int(digit) for i, digit in enumerate(digits))
return (result % 11) == check_digit
me queda bien. Me gusta tu uso de cortar. Como señaló la otra persona, su expresión ternaria se puede simplificar con solo regresar (resultado% 11) == check_digit – I82Much
También puede eliminar los "me gusta" en blanco, de acuerdo con PEP8 –
+1 para cosas excepcionalmente buenas primero y luego preguntando por mejoras. ¡Buen trabajo! – dotalchemy