Python在赋值前引用了局部变量

0 投票
3 回答
3123 浏览
提问于 2025-04-17 21:50

我正在为学校的计算机GCSE课程做一个货币转换器,但我不知道自己哪里出错了。

我的代码是:

PD = 1.66401 # declare pounds to dollars exchange rate

def Convert(ex): #converting sub... ex = exchange rate
    amount = input("Enter amount to convert: ") #get amount to convert
    result = round(float(amount) * float(ex),2) #calculate result using PD rate
    print("result = " + str(result)) #print result

def Change(ex): #change sub... ex = echange rate
    newex = input("Enter new exchange rate: ") #allow user to enter new exchange rate
    if ex == PD: #check what exchange rate to change (needed because final version will have alot more options
        PD = float(newex) #change exchange rate

#display menu
menu = input("1.Convert\n2.Modify exchange rate\nPlease select option: ")
if menu == "1":
    Convert(PD) #Call sub...convert using pounds to dollars
elif menu == "2":
    Change(PD) #Call sub...change pounds to dollars exchange rate

当我进行转换时,结果是正确的,但当我更改汇率时,我遇到了以下错误:

Traceback (most recent call last):
  File "F:/USB/Computing/Programming/Python/test2.py", line 18, in <module>
    Change(PD) #Call sub...change pounds to dollars echange rate
  File "F:/USB/Computing/Programming/Python/test2.py", line 10, in Change
    if ex == PD: #check what exchange rate to change (needed because final version will have alot more options
UnboundLocalError: local variable 'PD' referenced before assignment

我搜索了很多地方,但没有找到有用的答案。如果你能尽量简单地解释一下我哪里出错了,以及我应该怎么做,我会非常感激。

3 个回答

1

这是一个很好的例子,说明使用类会非常有帮助。通过把PD声明为类的属性,你可以使用@property装饰器,这样可以让你的代码更有条理,也不用担心全局变量的问题。

class CurrencyConverter(object):

    def __init__(self):
        """
        Set the default exchange rate to Pounds to U.S. Dollars
        """
        self.PD = 1.66401

    @property
    def PD(self):
        return self._PD

    @PD.setter
    def PD(self, value):
        """
        Set and ensure PD is a float value.
        """
        self._PD = float(value)

    def convert(self):
        """
        Takes user input and returns exchanged value.
        """
        amount = input("Enter amount to convert: ")
        result = round(float(amount) * self.PD, 2)
        print "result = %.2f\n" % result

    def change(self):
        """
        Takes user input and changes exchange rate.
        """
        newex = input("New exchange rate: ")
        self.PD = newex

使用这种方法的好处是,如果你下一个任务是扩展你的货币转换器,那么添加方法或者继承这个类就会变得很简单,比如这样:

class CanadianExchangeRate(CurrencyConverter):
    """
    Converts Canadian Dollars to U.S. Dollars.
    """
    def __init__(self):
        self.PD = 0.90
3
def Change(ex): #change sub... ex = echange rate
    global PD
    newex = input("Enter new exchange rate: ") #allow user to enter new exchange rate
    if ex == PD: #check what exchange rate to change (needed because final version will have alot more options
        PD = float(newex) #change exchange rate

更多信息请查看 Python 文档

当在代码块中使用一个名字时,Python 会从最近的外部范围中查找这个名字。所有这些代码块可见的范围被称为这个块的环境。

如果在一个代码块中给一个名字赋值,那么这个名字就是这个块的局部变量,除非你特别声明它为非局部变量。如果在模块级别给名字赋值,那么它就是全局变量。(模块代码块中的变量可以是局部的也可以是全局的。)如果在代码块中使用了一个变量,但没有在这里定义它,那么这个变量就是自由变量。

当找不到一个名字时,会抛出一个 NameError 异常。如果这个名字指向一个还没有被赋值的局部变量,会抛出一个 UnboundLocalError 异常。UnboundLocalError 是 NameError 的一个子类。

0

你可以在函数里面正常使用全局变量。但是,如果你想要修改这些变量的值,就需要先用 global 这个关键词,告诉程序这些变量是全局的:

def Change(ex):
    ##########
    global PD
    ##########
    newex = input("Enter new exchange rate: ")
    if ex == PD:
        PD = float(newex)

撰写回答