【问题标题】:cannot find attribute in imported file在导入的文件中找不到属性
【发布时间】:2012-08-06 16:05:30
【问题描述】:

我正在尝试为作为 rlg 导入的程序制作一个按钮界面。 rlg 有一个实时图形系统,其中两个变量可以随着模拟的进行而被测量和更新。我希望能够使这两个变量具有选择性,因此我在 rlg 的 main() 方法中创建了一个字典“graphLines”,其中下拉菜单上的每个字符串选择都充当一个键。但是我似乎无法访问它并收到错误消息:AttributeError:'function'对象没有属性'graphLines'。谁能看到我做错了什么。

from Tkinter import *
import runlivegraph3 as rlg

def run():
    rlg.main()

def setLine1(name):
    rlg.main.Line1data = rlg.main.graphLines[name] #graphlines is a dictionary in runlivegraph3 main method

def setLine2(name):
    rlg.main.Line2data = rlg.main.graphLines[name]


root = Tk()

var1 = StringVar()
var1.set("select graph line 1 data") #initial variable in drop down menu, each string is a key in the graphLines dictionary
op1 = OptionMenu(root, var1, 'Political attacks in turn',
                 'Ethnic attacks in turn',
                 'Total attacks in turn',
                 'Ethnic attacks as a percentage of total attacks',
                 'Political attacks as a percentage of total attacks',
                 'Group 1 ethnic antagonism',
                 'Group 2 ethnic antagonism',
                 command = setLine1).pack()


var2 = StringVar()
var2.set("select graph line 2 data") #initial variable in drop down menu
op2 = OptionMenu(root, var2, 'Political attacks in turn',
                 'Ethnic attacks in turn',
                 'Total attacks in turn',
                 'Ethnic attacks as a percentage of total attacks',
                 'Political attacks as a percentage of total attacks',
                 'Group 1 ethnic antagonism',
                 'Group 2 ethnic antagonism',
                 command = setLine2).pack()
butn = Button(root, text = 'run',  command = run)
butn.pack()
root.mainloop() 

这是我在 Tkinter 按钮程序中导入的程序的 main() 函数

from matplotlib.pylab import *
import sys, random, time, csv
def main():

IDs = {}
boardDims = (20,20)
Line1data = None
Line2data = None
turnLimit = 40
pause = 0.0001

ethnicPred = []
politicalPred = []
totalAttacks = []
generation = []
data1 = []
data2 = []
data3 = []
ethAnt1 = []
ethAnt2 = []
polAnt1 = []
polAnt2 = []
EthnicAttacksInTurn = []
PoliticalAttacksInTurn = []
TotalAttacksInTurn = []
ProportionEth = []
ProportionPol = []


board = make_board(boardDims)

finallyAddAgents(IDs, board, boardDims)
splitAgents(IDs)
setRemainingPolitics(IDs)
setPoliticalAntagonism(IDs)

turn = 0
line1, = plot(turn, 0, 'b')  #initialise lines
line2, = plot(turn, 0, 'r')
running = 1
while running:
    ion()   #sets up graph base and axes
    axes()
    xlim(0,turnLimit)
    ylim(0,30)
    if turn == turnLimit: running = 0
    print_board3(IDs, board, boardDims)
    print 'turn ', str(turn)
    polAttackTurn = []
    ethAttackTurn = []
    AllAgentsPerformActions(IDs, board,turn,ethnicPred, politicalPred,
                            totalAttacks,polAttackTurn,ethAttackTurn)

    totalAttackTurn = sum(ethAttackTurn) + sum(polAttackTurn)
    if totalAttackTurn != 0:
        propEth = (sum(ethAttackTurn)*100)/totalAttackTurn
        propPol = (sum(polAttackTurn)*100)/totalAttackTurn        
    if totalAttackTurn == 0:
        propEth = 0
        propPol = 0
    TotalAttacksInTurn.append(totalAttackTurn)
    EthnicAttacksInTurn.append(sum(ethAttackTurn))
    PoliticalAttacksInTurn.append(sum(polAttackTurn))
    ProportionEth.append(propEth)
    ProportionPol.append(propPol)



    k =  sum(politicalPred)
    j = sum(ethnicPred)
    #f = sum(totalAttacks)
    #print k, j, f
    data1.append(j)
    data2.append(k)
    #data3.append(f)
    generation.append(turn)
    for agent in IDs.values():
        if agent.group == '1':
            ethAnt1.append(agent.antagonism['2'])
            break
    for agent in IDs.values():
        if agent.group == '2':
            ethAnt2.append(agent.antagonism['1'])
            break
    for agent in IDs.values():
        if agent.politics == 'A':
            polAnt1.append(agent.polAntagonism['B'])
            break
    for agent in IDs.values():
        if agent.politics == 'B':
            polAnt2.append(agent.polAntagonism['A'])
            break
    #this is the dictionary i am trying to access from the Tkinter button program
    graphLines = {'Political attacks in turn':sum(polAttackTurn),
              'Ethnic attacks in turn':sum(ethAttackTurn),
              'Total attacks in turn':totalAttackTurn,
              'Ethnic attacks as a percentage of total attacks': propEth,
              'Political attacks as a percentage of total attacks': propPol,
              'Group 1 ethnic antagonism': ethAnt1[-1],
              'Group 2 ethnic antagonism': ethAnt2[-1]}

        line1.set_ydata(append(line1.get_ydata(), Line1data))
        line1.set_xdata(append(line1.get_xdata(), turn))
        line2.set_ydata(append(line2.get_ydata(), Line2data))
        line2.set_xdata(append(line2.get_xdata(), turn))
        draw()
        turn += 1 

【问题讨论】:

  • 到底是什么让您认为您可以将函数的变量作为该函数的属性来访问?我什至无法想象你认为这会做什么,或者你想做什么,用这样的结构。
  • 所以我无法从按钮文件中访问 graphLines 字典?我没有被正确地教过编程,所以我对“属性”的含义只有一个模糊的概念。
  • 好吧,它没有正确缩进,但是假设您的 graphLines = 行打算在您的 main() 函数内,graphLines 是该函数中的局部变量。该字典仅在 main() 运行时存在,并在函数结束时被丢弃。
  • 无论你遵循什么 Python 教程来学习 Python,都应该解释 attribute 的含义。
  • 所以唯一可访问的变量必须是全局的?那为什么 Line1data 和 Line2data 不会抛出同样的异常呢?

标签: python import tkinter attributeerror


【解决方案1】:

我想我最好把我的评论变成一个答案,所以我开始了。

您对变量和属性之间的区别感到困惑,因此我将通过一些示例来解释区别。您的问题实际上不是导入问题,而是更多关于范围和面向对象编程 (OOP) 的问题。

(例如 1) 要在函数中设置局部变量,您可以:

def spam():
    eggs = 5

(例如 2) 要在函数对象上设置属性(通常不那么合乎逻辑),您可以这样做:

def spam():
    pass
spam.eggs = 5

虽然这些看起来很相似,但它们的效果却大不相同。在第一个示例中,eggs 是函数 spam 中的一个局部变量。 在其定义函数内创建、访问和修改局部变量。

def spam():
    eggs = 5
print spam.eggs

但是会导致错误

def spam():
    pass
spam.eggs = 5
print spam.eggs

不会。在第二个示例中,eggs 是函数(对象)spam 的属性。它可以在对象的方法内或对象外创建、访问和修改,但不能在函数本身内作为局部变量(也因为函数不知道它的存在直到它是完全定义的)。因此,以下会引发错误:

def spam():
    print eggs
spam.eggs = 5
spam()

因为eggs 是一个属性,而不是一个局部变量。

如果你熟悉 OOP,这里有一些扩展:

第一个例子相当于:

class Spam(object):
    def __init__(self):
        eggs = 5

而第二个例子相当于:

class Spam(object):
    def __init__(self):
        self.eggs = 5

就OOP而言,区别只是第一个设置一个局部变量,而第二个设置一个实例变量。尝试在第一堂课上做Spam().eggs 没有意义,而在第二堂课上却可以。

最后,

要解决您的问题,请在函数之外定义您需要的变量,或者使用global 关键字来表明它们是全局的。示例用法:

def spam():
    global eggs
    eggs = 5
spam()
print eggs  # Prints 5

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-07-24
    • 2014-02-24
    • 2014-01-29
    • 1970-01-01
    • 2011-11-03
    • 2019-05-10
    • 2014-07-29
    • 1970-01-01
    相关资源
    最近更新 更多