Не удается найти атрибут в импортированном файле
Я пытаюсь сделать интерфейс кнопки для моей программы, которая импортируется как rlg. В rlg имеется система графического отображения, в которой можно измерять и обновлять две переменные в процессе генерации симуляции. Я хочу иметь возможность сделать эти две переменные селективными, поэтому я создал словарь graphLines в методе main() класса rlg, в котором каждый выбор строки в раскрывающемся меню выступает в качестве ключа. Однако я не могу получить к нему доступ и получить сообщение об ошибке: 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()
это функция main() программы, которую я импортирую в программу кнопки Tkinter
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
1 ответ
Я решил, что лучше превратить мой комментарий в ответ, так что я здесь.
Вы путаетесь между разницей между переменными и атрибутами, поэтому я объясню разницу на нескольких примерах. Ваш вопрос на самом деле не вопрос импорта, а больше о области видимости и объектно-ориентированном программировании (ООП).
(например, 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
является атрибутом, а не локальной переменной.
Если вы знакомы с ООП, вот несколько расширений:
Первый пример будет эквивалентен:
class Spam(object):
def __init__(self):
eggs = 5
в то время как второй пример будет эквивалентен:
class Spam(object):
def __init__(self):
self.eggs = 5
С точки зрения ООП, отличие состоит в том, что первый устанавливает локальную переменную, а второй устанавливает переменную экземпляра. Пытаюсь сделать Spam().eggs
в первом классе не имеет смысла, а во втором - может.
В заключение,
Чтобы решить вашу проблему, либо определите нужные переменные вне функции, либо используйте global
ключевое слово, чтобы показать, что они являются глобальными. Пример использования:
def spam():
global eggs
eggs = 5
spam()
print eggs # Prints 5