我的GTIN程序中的`NameError`是什么意思?

时间:2015-12-07 17:38:26

标签: python

请注意我是初学者。 以下程序是关于计算GTIN编号。基本上,不起作用的部分是验证部分。该程序应该验证代码并同时向用户解释它;然而,计算机似乎无法识别我出于某种原因使用的变量。验证选项仅在您确实计算了GTIN编号并且菜单重新出现后才可用(仅适用)询问您是否要重新运行该程序。我希望你能理解我的问题!非常感谢!以下是我的代码:

print("Welcome. Do you want to start? (Y/N)")
answer = input()

while(answer == "Y"):
    print("1. Calculate a GTIN number")
    print("2. Validate Previous Code (Please note that this option is only valid if you have just calculated a GTIN number)")
    print("3. End Program")
    option = int(input())

    def GTIN():
        #Step 1
        print("Enter the first digit of your GTIN code")
        digit_1 = int(input())

        print("Enter the second digit")
        digit_2 = int(input())

        print("Enter the third digit")
        digit_3 = int(input())

        print("Enter the fourth digit")
        digit_4 = int(input())

        print("Enter the fifth digit")
        digit_5 = int(input())

        print("Enter the sixth digit")
        digit_6 = int(input())

        print("Enter the seventh digit")
        digit_7 = int(input())

        #Step 2
        total_1 = digit_1 * 3
        total_2 = digit_2 * 1
        total_3 = digit_3 * 3
        total_4 = digit_4 * 1
        total_5 = digit_5 * 3
        total_6 = digit_6 * 1
        total_7 = digit_7 * 3

        #Step 3
        final_total = total_1 + total_2 + total_3 + total_4 + total_5 + total_6 + total_7


        #Step 4
        import math
        def roundup(final_total):
            return int(math.ceil(final_total / 10.0) * 10)

        final_total_2 = roundup(final_total)


        GTIN_number_8 = final_total_2 - final_total

        print("Your complete GTIN number is:", digit_1, digit_2, digit_3, digit_4, digit_5, digit_6, digit_7, GTIN_number_8)
        return digit_1, digit_2, digit_3, digit_4, digit_5, digit_6, digit_7, GTIN_number_8

    def validation(digits, totals):
        print("Your previous GTIN code:", digits[0], digits[1], digits[2])
        print("Firstly, the computer will collect all of the digits, then it will multiply them by either 3 or 1:")
        print("The 1st digit: ", digit_1, "will be multiplied by 3")
        print("The 2nd digit: ", digit_2, "will be mutliplied by 1")
        print("The 3rd digit: ", digit_3, "will be multiplied by 3")
        print("The 4th digit: ", digit_4, "will be mutliplied by 1")
        print("The 5th digit: ", digit_5, "will be multiplied by 3")
        print("The 6th digit: ", digit_6, "will be mutliplied by 1")
        print("The 7th digit: ", digit_7, "will be multiplied by 3")

        print("Secondly, the computer will add up all of the digits:")
        print("1st digit + 2nd digit + 3rd digit + 4th digit + 5th digit + 6th digit + 7th digit")
        print(total_1, "+", total_2, "+", total_3, "+", total_4, "+", total_5, "+", total_6, "+", total_7)
        print("Total =", final_total)

        print("Thirdly, the total will be rounded to the highest multiple of 10")
        print("The total rounded =", final_total_2)

        print("Lastly, the total will then be subtracted from the rounded number to give the GTIN number 8")
        print("Final GTIN number including the final digit:", digit_1, digit_2, digit_3, digit_4, digit_5, digit_6, digit_7, GTIN_number_8)

    def end():
        print("Ending Program")

    if(option == 1):
        GTIN(digits, totals)
    elif(option == 2):
        validation(digits)
    elif(option == 3):
        end()
    else:
        print("Ending Program")

    print("Do you want to re-run the program? (Y/N)")
    answer = input()


print("Ending Program")

'名称错误'消息是:

Traceback (most recent call last):
  File "G:\Year 10 - Computer Science\GCSE Coursework\Part One\Code Versions\GTIN Code V4.py", line 85, in <module>
    GTIN(digits, totals)
NameError: name 'digits' is not defined

3 个答案:

答案 0 :(得分:1)

来自https://docs.python.org/2/reference/executionmodel.html

  

范围定义块中名称的可见性。如果在块中定义了局部变量,则其范围包括该块。

在您的代码中,digit_1的值是在GTIN()函数的范围内分配的。这意味着它在该范围之外是不可见的 - 它是该函数的本地变量。因此,当您尝试从其他功能validation()访问它时,无法识别名称digit_1

设计此方法的最佳方法可能是制作同一GTIN( self )validation( self )方法,并创建并使用该类的实例。然后,如果要在类实例的方法之间共享变量,可以将它们指定为self属性 - 即使用self.digit_1当前只有digit_1 1}}。

在函数之间共享变量的更快更脏的解决方案是

global digit_1    #  , and all the other variables

GTIN()的开头(以及任何其他想要更改其值的函数)。这意味着GTIN()中发生的分配将在全局范围内(即整个文件的级别)生效,因此validate()将能够访问它们。

在目前的形式中,如果您在同一范围内执行所有操作,您的特定程序也将起作用(并且能够在代码块之间共享变量而无需考虑它)。这意味着完全摆脱def语句,并移动GTIN下的if option == 1代码块和validateelif option == 2的代码块。< / p>

答案 1 :(得分:1)

您应该更改validation功能的签名

def gtin_validate(gtin):
    # @param {str} gtin
    # @returns {bool}
    evens, odds = gtin[0:-1:2], gtin[1:-1:2]
    total = 0
    for even in evens:
        total += int(even) * 3
    for odd in odds:
        total += int(odd) * 1
    checkdigit = 10 - (total % 10)
    return checkdigit == int(gtin[-1])

慢慢地逐步完成这个功能:

def gtin_validate(gtin):
    # @param {str} gtin
    # @returns {bool}

新函数签名接受一个整个GTIN的字符串(例如"01234567"),如果GTIN有效,则返回True,如果不是,则返回False。我在这里使用Javadoc评论只是因为它对更广泛的程序员更熟悉,但目前的风格应该是:def gtin_validate(gtin: str) -> bool:

evens, odds = gtin[0:-1:2], gtin[1:-2:2]

这会抓取所有偶数序列号和所有奇数序列号(切掉最后一个字符)并将它们存储在相应的变量中。阅读s[i:j:k]

部分中的更多in the docs
total = 0
for even in evens:
    total += int(even) * 3
for odd in odds:
    total += int(odd) * 1

这只是总结数字。应该是自我描述的。事实上,sum([int(n) for n in itertools.chain(evens, odds)])就是我为那些不仅仅是刚出发的人写的!{/ p>

checkdigit = 10 - (total % 10)

这取代了您的想象“向上舍入到最接近的十的倍数并减去原始总数”公式。 total % 10是模数函数,它为您提供除法的余数而不是商(10 / 4 == 2.5,但是10 % 4 == 2)。这是一个绑定数字的好方法,模10是特殊的,因为它基本上给你一个正数的“一”位置。由于我们有“一个”的地方,我们可以从10减去它来获得我们的检查数字。

return checkdigit == int(gtin[-1])

现在我们只返回该checkdigit是否与我们的GTIN的最后一位数匹配。万岁!

答案 2 :(得分:0)

您需要传递digit_1,因为该函数只能查看其中定义的变量。这意味着您需要从digit_1返回GTIN。您需要对函数中定义的所有变量执行此操作。

由于您有许多这样的变量,将它们全部存储在名为digitstotalfinal_total的列表中更为简单,其中digit[0]将是您当前定义为digit_1的整数和digit_7将是gtin_number_8中当前定义的整数。您应该为totalsfinal_total创建另一个列表。要在不更改整个代码的情况下实现此目的,我建议如下。

def GTIN():的最后几行应为:

digits = [digit_1, digit_2, digit_3, digit_4, digit_5, digit_6, digit_7, GTIN_number_8]
#create a totals list in similar way
#create a final_totals list in similar way
return digits, totals, final_totals

然后当你调用GTIN()时,确保存储返回的变量。定义验证时,请确保您可以传递digitstotalsfinal_totals

if(option == 1):
    digits, totals, final_totals = GTIN()
elif(option == 2):
    validation(digits, totals, final_totals)

我包含了你的函数应该如何为前三个数字的列表编制索引,但这对于所有值都是类似的。请注意,gtin_number_8存储在digits[7]

def validation(digits, totals, final_totals):
    print("Your previous GTIN code:", digits[0], digits[1], digits[2])

我强烈建议将import math移到代码的第一行。模块只导入一次并保留整个会话,因此每次运行该函数时都不需要导入模块。

编辑:我以前忘了通过总计,final_totals。