如何让eval()执行我定义的函数? [蟒蛇]

时间:2014-10-21 02:27:38

标签: python-3.x eval

我需要在python 3.4.1中评估一些代码

def foo(bar):
    somecode
def myFunction(codeInString):
    eval("foo(" + codeInString + ")")

但是每当我尝试评估它时,我都会收到错误消息     NameError:名称'foo'不是

当我使用'q Patrick m 1880 1885 2'作为输入时,它应该给我一个三元组的列表。相反,我得到了 File "C:\...\Project 1\names.py", line XXX, in BBNInput return(eval("getBirthsByName(" + query + ")")) File "<string>", line 1, in <module> NameError: name 'getBirthsByName' is not defined

我在代码块

下面定义了tiny_names.csv
import matplotlib.pyplot as plt
import string

def names( infile = 'tiny_names.csv'):
    #This takes in the name of the file containing the clean name data and returns a list in the format [year, name, sex, quantity]
    def readNames(infile = 'tiny_names.csv'):

        #Counts the number of name-year combinations
        counter = 0
        #Opens the file
        file = open(infile, 'r')
        #Reads each line into an item on the list
        names = [i for i in file]
        #Formatting
        for i in names:
            #increments the counter
            counter = counter + 1
            index = names.index(i)
            #Removes the newline char
            names[index] = i.strip('\n')    
            #splits by the comma
            names[index] = names[index].split(',')
            #reformats the numbers into ints, makes names all lowercase to make searching easier
            names[index] = [ int(names[index][0]), names[index][1].lower(), names[index][2], int(names[index][3])]
        #closes the file
        file.close()

        #returns the names
        return(names)



    #Takes names as an argument and returns a dictionary with keys of names and values of lists of tuples (year, male births, female births)
    def nameIndex(names):
        #Initialize the empty dictionary
        result = {}
        for i in names:
            name = i[1]
            if name not in result.keys():
                #if it's a male, add in the male format
                if i[2] == 'M':
                    result[name] = [(i[0], i[3], 0)]
                #otherwise, add in the female format
                else:
                    result[name] = [(i[0], 0, i[3])]
            #Checking if there is already a datapoint for that year
            elif True in [( i[0] == a[0]) for a in result[name]]:
                xx = [( i[0] == a[0]) for a in result[name]]
                index = xx.index(True)
                #If there is a datum in the male slot, add the new datum to the female slot
                if result[name][index][1] == 0:
                    result[name][index] = (result[name][index][0], i[3], result[name][index][2])
                #Otherwise, vice versa
                else:
                     result[name][index][2] == (result[name][index][0], result[name][index][1], i[3])
            #if the name exists but the year is unique
            else:
                #if it is a male, add it in the male format
                if i[2] == 'M':
                    result[name].append((i[0], i[3], 0))
                #otherwise add it in the female format
                else:
                    result[name].append((i[0], 0, i[3]))
        #Return the results
        return(result)




    def getBirthsByName (name , gender=None, start=None, end=None, interval=None):
        #initialize the return variable
        thing = []
        #Make the name variable auto match the format of the names 
        name = name.lower()
        #if the name doesn't exist, say so
        if name not in nameIndex:
            return("Name not in index")
        #if there are no time constraints
        if not start and not end and not interval:
            #cycle through the name Data Points (dp) and addup the numbers for
            for dp in nameIndex[name]:
                year = dp[0]
                #Gender neutral
                if not gender:
                    thing.append((year, dp[1] +dp[2]))
                #Males
                elif gender.upper() == "M":
                    thing.append((year, dp[1]))
                #Females
                elif gender.upper() == "F":
                    thing.append((year, dp[2]))
                #Data validation, gender != m or f
                else:
                    return("You have entered and invalid gender, because we are insensitive people")
        else:
            #Data Validation, see return comments
            if interval and (not start or not end):
                return("You must have a start and an end to have an interval")
            if not end:
                end = 2013 #initializes end if blank
                if start:
                    return("You must have a start to have an end")
            if not start:
                start = 1880 #initializes start if blank
            if not interval:
                interval = 1 #initializes interval if blank
            #If the input passes all the validation tests, return data
            for year in range (start, end, interval):
                if year not in yearIndex.keys():
                    continue
                if name not in yearIndex.get(year).keys():
                    continue

                #Assign the tuple to dp
                dp = yearIndex.get(year).get(name)
                #Gender neutral
                if not gender:
                    thing.append((year, dp[0] +dp[1]))
                #Males
                elif gender.upper() == "M":
                    thing.append((year, dp[0]))
                #Females
                elif gender.upper() == "F":
                    thing.append((year, dp[1]))
        return(thing)    



    def BBNInput(inp):
        split = inp[2:].split()
        query = '"' + split[0] + '"'
        if (split[1] != None):
            query = query + ',"' + split[1] + '"'
        if (split[2] != None):
            query = query + "," + split[2] 
        if (split[3] != None):
            query = query + "," + split[3] 
        if (split[4] != None):
            query = query + "," + split[4]
        return(eval("getBirthsByName(" + query + ")"))



    #read the names
    print("read the names")
    nameList = readNames()
    #store the name index
    print("make the name index")
    nameIndex = nameIndex(nameList)


    #initialize the exit bool
    exit = False

    #Functional loop
    while not exit:
            queue = []
            inp = input('names> ')
            if inp == 'x':
                exit = True
                continue
            elif inp[0] == 'c':
                data = BBNInput(inp)
                total = 0
                for dp in data:
                    total = total + dp[1]
                print(total)
            elif inp[0] == 'q':
                print(BBNInput(inp))
            elif inp[0] == 'p':
                split = inp[2:].split()
                query = '"' + split[0] + '"'
                if (split[1] != None):
                    query = query + ',"' + split[1] + '"'
                if (split[2] != None):
                    query = query + "," + split[2] 
                if (split[3] != None):
                    query = query + "," + split[3] 
                if (split[4] != None):
                    query = query + "," + split[4] 

                exec("print(getBirthsByName(" +query + "))")



names()

tiny_names.csv =

    1890,Patrick,M,227
1890,Mary,F,12078
1890,Charles,M,4061
1890,Alice,F,2271
1889,Patrick,M,236
1889,Mary,F,11648
1889,Charles,M,4199
1889,Alice,F,2145
1888,Patrick,M,245
1888,Mary,F,11754
1888,Charles,M,4591
1888,Alice,F,2202
1887,Patrick,M,218
1887,Mary,F,9888
1887,Charles,M,4031
1887,Alice,F,1819
1886,Patrick,M,249
1886,Mary,F,9890
1886,Charles,M,4533
1886,Alice,F,1811
1885,Patrick,M,217
1885,Mary,F,9128
1885,Charles,M,4599
1885,Alice,F,1681
1884,Patrick,M,222
1884,Mary,F,9217
1884,Charles,M,4802
1884,Alice,F,1732
1883,Patrick,M,213
1883,Mary,F,8012
1883,Charles,M,4826
1883,Alice,F,1488
1882,Patrick,M,249
1882,Mary,F,8148
1882,Charles,M,5092
1882,Alice,F,1542
1881,Patrick,M,188
1881,Mary,F,6919
1881,Charles,M,4636
1881,Alice,F,1308
1880,Patrick,M,248
1880,Mary,F,7065
1880,Charles,M,5348
1880,Alice,F,1414

2 个答案:

答案 0 :(得分:0)

好吧,现在我觉得有太多代码可以明显看出问题所在。但是,您可能根本不需要使用eval()。以下可能会做你想要的:

def BBNInput(inp):
    split = inp[2:].split()
    return getBirthsByName(*split)

有关这意味着什么的详细信息,请参阅What does ** (double star) and * (star) do for Python parameters?

答案 1 :(得分:0)

我通过将我的BBNInput函数更改为查询构建函数来修复它,并在与getBirthsByName的def相同的级别上进行评估(使用eval())。但我认为@GregHewgill有权利,更有道理。谢谢大家的帮助!