我编码了一个用于检查公司人格的增值税编号数字的函数。该功能起作用,但这很丑陋(太长又太复杂了)。
我是新的编程Python,想改善功能,因此我需要一些反馈和帮助。
增值税号码总是9位数字,首先是char,其余为数字。
char必须在letras
字符串中。
最后一个数字是支票数字。
使用其他七个数字,算法是:
- 以次数为单位的数字。
- 奇数顺序的数字被乘以2(每个),如果每个结果的结果为> 10,则将单位添加到数十个中,然后四个结果被划分。
- 添加了步骤1和2中的小写。
- 获取单位,如果是0,则支票数字为0,在其他情况下为扣除10。结果是支票数字。
有效增值税号的一个示例是A58818501
代码
def validarCodigoCIF(entrada):
"""
:param: entrada: str
:rtype: bool
"""
letras = "ABCDEFGHIJKLMNPQRSVW"
if len(entrada) != 9 or entrada[0] not in letras:
return False
numero = entrada[1:10]
pares = int(numero[1]) + int(numero[3]) + int(numero[5])
impares = 0
for i in range(0, 8, 2):
j = int(numero[i]) * 2
if j < 10:
impares += j
else:
impares += j - 9
digito = str(pares+impares)[-1]
if int(digito) == 0:
checkCIF = 0
else:
checkCIF = 10 - int(digito)
# print(checkCIF)
if str(checkCIF) == entrada[-1]:
return True
else:
return False
entradaCodigoCIF = input('Enter the VAT number: ')
print(validarCodigoCIF(entradaCodigoCIF))
这是一个缩短版本
def check(vat_num):
if len(vat_num) != 9 or vat_num[0] not in "ABCDEFGHIJKLMNPQRSVW":
return False # trivial checks first
nums = list(map(int, vat_num[1:8])) # numbers to check
nums[1::2] = ((i * 2) - (9 if i > 4 else 0) for i in nums[1::2]) # alter odds
return int(vat_num[8]) == (sum(nums) % 10) # compare to check digit
请注意以下有趣的*功能:
- 使用
[1::2]
从峰值获取其他所有项目 - 使用
map(int, ...)
将相互关系中的所有项目转换为整数;和 - 使用
% 10
(Modulo)轻松获得数字的数字部分。
*可能不有趣
要解决的第一个问题是您的功能太长:
def calculate_pares(numero):
return int(numero[1]) + int(numero[3]) + int(numero[5])
def calculate_impares(numero):
result = 0
for i in range(0, 8, 2):
j = int(numero[i]) * 2
if j < 10:
result += j
else:
result += j - 9
return result
def calculate_check_cif(entrada):
numero = entrada[1:10]
pares = calculate_pares(numero)
impares = calculate_impares(numero)
digito = str(pares+impares)[-1]
if int(digito) == 0:
return 0
return 10 - int(digito)
def validarCodigoCIF(entrada):
"""
:param: entrada: str
:rtype: bool
"""
letras = "ABCDEFGHIJKLMNPQRSVW"
if len(entrada) != 9 or entrada[0] not in letras:
return False
checkCIF = calculate_check_cif(entrada)
# print(checkCIF)
return str(checkCIF) == entrada[-1]
这只是第一步,我认为您明白了。然后,当您拥有较小的功能时,进一步的改进会更容易。
另外,如果您用英语编写代码会更容易 - 那么人们可能会帮助您发现更多有意义的功能,而不是通过盲目分配/猜测。
查看增值税编号使用luhn checksum,我介绍了我最近在(未接受的)关于信用卡号码的答案中发布的修改版本。
该函数不一定比您的短,而是使用另一种方法:它在有效数字上返回None
,而故障上的简短错误消息。它还确保了首字母后的数字有效,并允许空间和一些标点符号。
def invalid_cif_code(s):
""" Returns None if s is a valid CIF code and a string
describing the error otherwise. The string may contain
spaces and punctuation, which is ignored.
"""
# strip punctuation from string
s = [x for x in s if x not in " t.-"]
if len(s) != 9:
return "Invalid length"
if s[0] not in "ABCDEFGHIJKLMNPQRSVW":
return "Invalid initial letter"
# convert numerical part to list of digits
try:
code = [int(x) for x in s[1:]]
except ValueError:
return "Invalid non-digit in number"
# multiply and cast out nines for every other codeit
for i in range(0, 8, 2):
code[i] *= 2
if code[i] > 9:
code[i] -= 9
# calculate checksum
s = (9 * sum(code)) % 10
if s != 0:
return "Invalid checksum"
return None
典型的程序员对Luhn校验和使用更优雅的解决方案(尽管已应用于信用卡号并用JavaScript编写),该解决方案使用奇数数组的数组。