【问题标题】:undefined error when passing list as parameter in python在python中将列表作为参数传递时出现未定义的错误
【发布时间】:2020-05-15 21:53:27
【问题描述】:

所以我之前设置了我的代码来访问一个在函数外部声明的列表,使其成为一个全局变量,因为我被分配给讲师的任务是坚持我们不使用全局变量。所以现在我有以下代码,它显然给出了“data_set undefined error”

我的想法是我从 csv 文件创建一个列表,然后将该列表传递给其他几个函数,以便我可以从 data_set 列表中获取元素并创建新的输出。

import csv
import sys

def print_menu():
    print("ACME WEATHER DATA APP")
    print("1) Choose weather data file")
    print("2) See data for selected day")
    print("3) Calculate average statistics for the data")
    print("4) Print a scatterplot of the average temperatures")
    print("0) Quit program")

def loadFile(x):
    data_set = []
    data_set.clear()
    with open(x, "r") as readfile:
        csv_reader = csv.reader(readfile, delimiter= ';')
        for row in csv_reader:
            data_set.append(row)
    print("Loaded weather data from", (x[0:-4]).capitalize())
    print()
    return data_set    

def avgDay(x, data_set):
    for line in data_set:
        if(len(x) == 5 and (x[3:5] + "-" + x[0:2]) in line[0]):
           print("The weather on", x, "was on average", line[2], "centigrade")


def lowHigh(x, data_set):
    for line in data_set:
        if(len(x) == 5 and (x[3:5] + "-" + x[0:2]) in line[0]):
            print("The lowest temperature was", line[3], "and the highest temperature was", line[4])


def rain(x, data_set):
    for line in data_set:
        if(len(x) == 5 and (x[3:5] + "-" + x[0:2]) in line[0]):
            print("There was", line[1],"mm rain")
            print()

def avgMonth(data_set):
    avgList= []
    for line in data[1:]:
        avgList.append(line[2])
    avgList= [float(i) for i in avgList]
    avg = sum(avgList)/len(avgList)
    print("The average temperature for the 25 day period was", round(avg,1))


def avgLow(data_set):
    avgList= []
    for line in data[1:]:
        avgList.append(line[3]) 
    avgList= [float(i) for i in avgList]
    avg = sum(avgList)/len(avgList)
    print("The average lowest temperature was", round(avg,1))


def avgHigh(data_set):
    avgList= []
    for line in data[1:]:
        avgList.append(line[4])  
    avgList= [float(i) for i in avgList]
    avg = sum(avgList)/len(avgList)

    print("The average highest temperature was", round(avg,1))
    print()

def print_tempLine(day, month, temp):
    print(day + "." + month + " ", end="")
    print("   "*(temp+5) + "-", end="")
    print()


def print_tempAxis():
    print("      ", end="")
    for i in range(-5,16):
        print("{:02d} ".format(i), end="")
    print()

def scatPlot(data_set):
    for line in data[1:]:
            day_month=line[0].split("-")
            temp=int(round(float(line[2]),0))
            print_tempLine(day_month[2],day_month[1],temp)
            print_tempAxis()
            print()

def menu_number():
    number = int(input("Choose what to do: "))
    if (number) == 1:
        x = input("Give name of the file: " )
        loadFile(x)
        print_menu()
        menu_number()

    elif (number) == 2:
        x = input("Give a date (dd.mm): ")
        avgDay(x, data_set)
        lowHigh(x, data_set)
        rain(x, data_set)
        print_menu()
        menu_number()

    elif (number) == 3:
        avgMonth(data_set)
        avgLow(data_set)
        avgHigh(data_set)
        print_menu()
        menu_number()

    elif (number) == 4:
        scatPlot(data_set)
        print_menu()
        menu_number()

    elif (number) == 0:
        sys.exit()

    else:
        print("\n Your selection is invalid, please try again!\n")
        print_menu()
        menu_number()

print_menu()
menu_number()

我知道当我在我的 loadFile(x) 中返回 data_set 时,它需要以某种方式分配给一个变量,以便可以在本地范围之外访问它,我只是不确定这是如何完成的。我尝试在 menu_number 函数中将loadFile(x) 更改为data_set = loadFile(x),这只是导致它给出以下错误“在赋值之前引用的局部变量'data_set'”。那么我是否遗漏了什么或者我需要以某种方式重新编写代码?

编辑:抱歉没有意识到我需要提供完整的堆栈跟踪错误

Traceback (most recent call last):
  File "C:\Users\alexa\Documents\XAMK\python scripts\test.py", line 126, in <module>
    menu_number()
  File "C:\Users\alexa\Documents\XAMK\python scripts\test.py", line 95, in menu_number
    menu_number()
  File "C:\Users\alexa\Documents\XAMK\python scripts\test.py", line 99, in menu_number
    avgDay(x, data_set)
NameError: name 'data_set' is not defined

编辑 2:csv 示例代码

"DateTime";"Precipitation";"Mean temperature";"Minimum temperature";"Maximum temperature";"Typical maximum temperature";"Typical maximum temperature";"Typical minimum temperature";"Typical minimum temperature";"Fairly typical maximum temperature";"Fairly typical maximum temperature";"Fairly typical minimum temperature";"Fairly typical minimum temperature"
"2019-10-06";0;4;0.4;6.8;10.3;11.9;4.5;7.2;7.6;13.8;0.9;9.8
"2019-10-07";0.1;4.4;2.6;7.8;10.1;11.8;4.4;7;7.4;13.6;0.8;9.7
"2019-10-08";0;4.9;2.3;7.2;10;11.6;4.2;6.9;7.2;13.4;0.6;9.5
"2019-10-09";1.1;4.8;1.8;7.6;9.8;11.4;4.1;6.7;6.9;13.3;0.5;9.4

【问题讨论】:

  • 发布完整的错误消息,包括堆栈跟踪。你真的需要提供minimal reproducible example,而不是把你的整个代码都放在这里。
  • 函数返回,而不是名称。如果您想使用返回的值,您需要...使用它,例如将其存储在某处。编写add(1, 2)(假设您实现了这样的功能)与编写1 + 2 相同——3 结果本身不会做任何事情(如果有的话,名称无关紧要) add 函数内部用于该结果)。

标签: python list parameters scope


【解决方案1】:

如果您能提供一个示例 csv 文件以便我可以测试工作流程,那将会很有帮助。但看起来问题在于您调用了loadFile(x),它有一个return 语句,但没有为该返回语句设置任何内容。所以你在data_set = loadFile(x) 的正确轨道上。问题是,当您再次调用menu_number 函数时,变量值不会被保留。所以在第二次通话中,data_set 失去了意义。

您可以通过将 data_set 的值传递给函数来解决此问题,因此您的 menu_number 看起来更像

def menu_number(data_set=None):
    number = int(input("Choose what to do: "))
    if (number) == 1:
        x = input("Give name of the file: " )
        data_set=loadFile(x)
        print_menu()
        # passing data_set value along
        # with the call
        menu_number(data_set)

    elif (number) == 2:
        x = input("Give a date (dd.mm): ")
        avgDay(x, data_set)
        lowHigh(x, data_set)
        rain(x, data_set)
        print_menu()
        # passing data_set to preserve it
        menu_number(data_set)

    elif (number) == 3:
        avgMonth(data_set)
        avgLow(data_set)
        avgHigh(data_set)
        print_menu()
        # passing data_set to preserve it
        menu_number(data_set)

    elif (number) == 4:
        scatPlot(data_set)
        print_menu()
        # passing data_set to preserve it
        menu_number(data_set)

    elif (number) == 0:
        sys.exit()

    else:
        print("\n Your selection is invalid, please try again!\n")
        print_menu()
        # passing data_set to preserve it
        menu_number(data_set)

在本例中,data_set 是一个可选变量。如果你打电话给menu_number()data_set 就是None。但是在您调用menu_number(data_set) 时,您可以重复使用该值。

将 data_set 设为可选参数将防止任何未定义的错误。将其传递回自身将避免您需要一遍又一遍地读取 csv 文件。

【讨论】:

  • 嗯,这可能是我所缺少的,有没有办法上传我正在使用的文件之一以及这里的问题?
  • 老实说不确定。如果您只是在代码块中粘贴了几行 csv,就像您对函数所做的那样,那对我来说就可以了。我扩展了我的示例以显示整个函数更新。
  • 在我正在使用的一个 csv 文件的前几行中添加,将测试您的建议,看看是否能解决我的问题,谢谢。
  • 谢谢。如果你有麻烦让我知道。我对此进行了测试并发现了另一个错误,在您的某些函数中,您有“for line in data[1:]”,但您传递的变量是 data_set。所以你也需要更新它。
  • 再次感谢您,我没有太多使用 python 的实践经验,而且我所经历的教程也没有像我需要的那样处理通过多个函数传递返回值。
【解决方案2】:

1) 您必须执行data_set = loadFile() 才能收到loadFile() 返回的列表。

2) 现在,关于"local variable 'data_set' referenced before assignment" 错误,它可能发生在number 不等于1 时,这会导致您的代码跳过data_set = loadFile(),并结合data_set 无法识别的事实在if 语句之外,只要您不在更高的范围(例如函数的开头)声明它,像avgDay(x, data_set) 这样的函数将不会将data_set 识别为多变的。 我建议解决这个问题:

1) 在更高的范围内声明data_set

2) 用户可以选择的每个动作都在data_set 上被初始化,在loadFile() 中初始化也必须包括这个初始化

【讨论】:

    猜你喜欢
    • 2021-12-31
    • 2021-01-14
    • 2013-05-06
    • 1970-01-01
    • 2011-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多