尝试访问ID时发生超级AttributeError

时间:2019-07-19 17:33:47

标签: python python-3.x kivy

我正在尝试用kivy编写minesweeper,并希望从Cell类中访问GameBoard类中的单元列表。我在扫雷器窗口中单击一个单元,这会产生错误。我是新手,但是我认为Ids是我要这样做的方式。

错误提示  AttributeError:“超级”对象没有属性“ getattr

我正在使用Python 3.7.3

我查看了有关使用ID或类似错误的所有问题,但是我没有遇到问题的答案,或者没有将它们识别为答案。

我尝试使用root,不使用root,将id作为字符串,不将id作为字符串以及许多其他小的更改来尝试修复它。

这是我正在使用的代码(.py):

import time
import random
import kivy
from kivy.app import App
from kivy.uix.button import Label
from kivy.uix.button import Button

from kivy.uix.gridlayout import GridLayout
from kivy.core.window import Window

class Cell(Button):
    def __init__(self, text, loc, board, **kwargs):
        super(Cell, self).__init__(**kwargs)
        self.size = (25,25)
        self.board = board
        self.loc = loc
        self.text = text
        self.val = 0
        self.bind(on_touch_up = self.onPress)
        self.visible = False
        self.app = App.get_running_app()

    def onPress(self, instance, touch):
        if self.collide_point(*touch.pos):
            if self.visible == False:
                self.visible = True
                if touch.button == 'right':
                    if self.text == '!':
                        self.text = '?'
                    else:
                        self.text = '!'
                elif touch.button == 'left':
                    self.text = self.val
                    if self.val == 'X':
                        None
                    elif self.val == '0':
                        self.revealNeighbors(self.loc[0],self.loc[1])
                    else:
                        None

    def revealNeighbors(self,y,x):
        for i in range(-1,2):
            for j in range(-1,2):
                if (0 <= (self.loc[0] + i) < self.board[0]) and (0 <= (self.loc[1] + j) < self.board[1]):
                    print(self)
                    if self.app.root.ids.myboard.cells[i][j].visible != True:
                        self.app.ids.myboard.cells[i][j].visible = True
                        self.app.ids.myboard.cells[i][j].text = self.app.ids.myboard.cells[i][j].val
                        if self.app.ids.myboard.cells[i][j].val == '0':
                            self.app.root.ids.myboard.cells[i][j].revealNeighbors(self.app.ids.myboard.cells[i][j],i,j)


        None


class GameBoard(GridLayout):
    def __init__(self, **kwargs):
        id: myboard
        name: "Board"
        super(GameBoard, self).__init__(**kwargs)

        self.row_force_default = True
        self.row_default_height = 30
        self.col_force_default = True
        self.col_default_width = 30

        self.cols = 30
        self.rows = 16
        Window.size = (self.cols * self.col_default_width, self.rows * self.row_default_height)
        self.cells = list()
        mines = 0
        minelst = list()

        self.score = 0

        for i in range(self.rows):
            temp = list()
            for j in range(self.cols):
                newCell = Cell(text = '0',loc = [i,j], board = [self.rows,self.cols])
                temp.append(newCell)
                self.add_widget(temp[-1])
            self.cells.append(temp)

        for k in range(mines):
            randX = random.randint(0,self.cols - 1)
            randY = random.randint(0,self.rows - 1)
            while self.cells[randY][randX].text == 'X':
                randX = random.randint(0,self.cols - 1)
                randY = random.randint(0,self.rows - 1)
            self.cells[randY][randX].text = 'X'
            temp = list()
            temp.append(randY)
            temp.append(randX)
            minelst.append(temp)
        minelst.sort()

        for mine in minelst:
            if mine[0] == 0: # first row
                if mine[1] == 0: # top-left corner
                    if self.cells[0][1].text != 'X':
                        self.cells[0][1].text = str(int(self.cells[0][1].text) + 1)
                    if self.cells[1][0].text != 'X':
                        self.cells[1][0].text = str(int(self.cells[1][0].text) + 1)
                    if self.cells[1][1].text != 'X':
                        self.cells[1][1].text = str(int(self.cells[1][1].text) + 1)
                elif mine[1] == (self.cols -1): # top-right corner
                    if self.cells[0][self.cols -2].text != 'X':
                        self.cells[0][self.cols -2].text = str(int(self.cells[0][self.cols -2].text) + 1)
                    if self.cells[1][self.cols -1].text != 'X':
                        self.cells[1][self.cols -1].text = str(int(self.cells[1][self.cols -1].text) + 1)
                    if self.cells[1][self.cols -2].text != 'X':
                        self.cells[1][self.cols -2].text = str(int(self.cells[1][self.cols -2].text) + 1)
                else:
                    if self.cells[0][mine[1]-1].text != 'X':
                        self.cells[0][mine[1]-1].text = str(int(self.cells[0][mine[1]-1].text) + 1)
                    if self.cells[0][mine[1]+1].text != 'X':
                        self.cells[0][mine[1]+1].text = str(int(self.cells[0][mine[1]+1].text) + 1)
                    for i in range(3):
                        if self.cells[1][(mine[1]-1)+i].text != 'X':
                            self.cells[1][(mine[1]-1)+i].text = str(int(self.cells[1][(mine[1]-1)+i].text) + 1)
            elif mine[0] == (self.rows -1): # bottom row
                if mine[1] == 0: # bottom-left corner
                    if self.cells[self.rows -1][1].text != 'X':
                        self.cells[self.rows -1][1].text = str(int(self.cells[self.rows -1][1].text) + 1)
                    if self.cells[self.rows -2][0].text != 'X':
                        self.cells[self.rows -2][0].text = str(int(self.cells[self.rows -2][0].text) + 1)
                    if self.cells[self.rows -2][1].text != 'X':
                        self.cells[self.rows -2][1].text = str(int(self.cells[self.rows -2][1].text) + 1)
                elif mine[1] == (self.cols -1): # bottom-right corner
                    if self.cells[self.rows -1][self.cols -2].text != 'X':
                        self.cells[self.rows -1][self.cols -2].text = str(int(self.cells[self.rows -1][self.cols -2].text) + 1)
                    if self.cells[self.rows -2][self.cols -1].text != 'X':
                        self.cells[self.rows -2][self.cols -1].text = str(int(self.cells[self.rows -2][self.cols -1].text) + 1)
                    if self.cells[self.rows -2][self.cols -2].text != 'X':
                        self.cells[self.rows -2][self.cols -2].text = str(int(self.cells[self.rows -2][self.cols -2].text) + 1)
                else:
                    if self.cells[self.rows -1][mine[1]-1].text != 'X':
                        self.cells[self.rows -1][mine[1]-1].text = str(int(self.cells[self.rows -1][mine[1]-1].text) + 1)
                    if self.cells[self.rows -1][mine[1]+1].text != 'X':
                        self.cells[self.rows -1][mine[1]+1].text = str(int(self.cells[self.rows -1][mine[1]+1].text) + 1)
                    for i in range(3):
                        if self.cells[self.rows -2][(mine[1]-1)+i].text != 'X':
                            self.cells[self.rows -2][(mine[1]-1)+i].text = str(int(self.cells[self.rows -2][(mine[1]-1)+i].text) + 1)
            elif mine[1] == 0: # left column w/o corners
                if self.cells[mine[0]-1][0].text != 'X':
                    self.cells[mine[0]-1][0].text = str(int(self.cells[mine[0]-1][0].text) + 1)
                if self.cells[mine[0]+1][0].text != 'X':
                    self.cells[mine[0]+1][0].text = str(int(self.cells[mine[0]+1][0].text) + 1)
                for i in range(3):
                    if self.cells[(mine[0]-1)+i][1].text != 'X':
                        self.cells[(mine[0]-1)+i][1].text = str(int(self.cells[(mine[0]-1)+i][1].text)+1)
            elif mine[1] == (self.cols -1): # right column w/o corners
                if self.cells[mine[0]-1][self.cols -1].text != 'X':
                    self.cells[mine[0]-1][self.cols -1].text = str(int(self.cells[mine[0]-1][self.cols -1].text) + 1)
                if self.cells[mine[0]+1][self.cols -1].text != 'X':
                    self.cells[mine[0]+1][self.cols -1].text = str(int(self.cells[mine[0]+1][self.cols -1].text) + 1)
                for i in range(3):
                    if self.cells[(mine[0]-1)+i][self.cols -2].text != 'X':
                        self.cells[(mine[0]-1)+i][self.cols -2].text = str(int(self.cells[(mine[0]-1)+i][self.cols -2].text)+1)
            else: # interior mines
                for i in range(3):
                    if self.cells[mine[0]-1][(mine[1]-1)+i].text != 'X':
                        self.cells[mine[0]-1][(mine[1]-1)+i].text = str(int(self.cells[mine[0]-1][(mine[1]-1)+i].text)+1)
                    if self.cells[mine[0]+1][(mine[1]-1)+i].text != 'X':
                        self.cells[mine[0]+1][(mine[1]-1)+i].text = str(int(self.cells[mine[0]+1][(mine[1]-1)+i].text)+1)
                if self.cells[mine[0]][mine[1]-1].text != 'X':
                    self.cells[mine[0]][mine[1]-1].text = str(int(self.cells[mine[0]][mine[1]-1].text)+1)
                if self.cells[mine[0]][mine[1]+1].text != 'X':
                    self.cells[mine[0]][mine[1]+1].text = str(int(self.cells[mine[0]][mine[1]+1].text)+1)

        for i in range(self.rows):
            for j in range(self.cols):
                self.cells[i][j].val = self.cells[i][j].text
                self.cells[i][j].text = '?'

class MineSweeper(App):
    def build(self):
        self.root = GameBoard()
        return self.root

mineSweeper = MineSweeper()

mineSweeper.run()

当我尝试访问ID时,会得到以下追溯:

 Traceback (most recent call last):
   File "kivy/properties.pyx", line 860, in kivy.properties.ObservableDict.__getattr__
 KeyError: 'myboard'

 During handling of the above exception, another exception occurred:

 Traceback (most recent call last):
   File "MineSweeper.py", line 183, in <module>
     mineSweeper.run()
   File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/kivy/app.py", line 855, in run
     runTouchApp()
   File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/kivy/base.py", line 504, in runTouchApp
     EventLoop.window.mainloop()
   File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/kivy/core/window/window_sdl2.py", line 747, in mainloop
     self._mainloop()
   File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/kivy/core/window/window_sdl2.py", line 479, in _mainloop
     EventLoop.idle()
   File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/kivy/base.py", line 342, in idle
     self.dispatch_input()
   File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/kivy/base.py", line 327, in dispatch_input
     post_dispatch_input(*pop(0))
   File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/kivy/base.py", line 233, in post_dispatch_input
     listener.dispatch('on_motion', etype, me)
   File "kivy/_event.pyx", line 707, in kivy._event.EventDispatcher.dispatch
   File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/kivy/core/window/__init__.py", line 1406, in on_motion
     self.dispatch('on_touch_up', me)
   File "kivy/_event.pyx", line 707, in kivy._event.EventDispatcher.dispatch
   File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/kivy/core/window/__init__.py", line 1442, in on_touch_up
     if w.dispatch('on_touch_up', touch):
   File "kivy/_event.pyx", line 707, in kivy._event.EventDispatcher.dispatch
   File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/kivy/uix/widget.py", line 571, in on_touch_up
     if child.dispatch('on_touch_up', touch):
   File "kivy/_event.pyx", line 703, in kivy._event.EventDispatcher.dispatch
   File "kivy/_event.pyx", line 1214, in kivy._event.EventObservers.dispatch
   File "kivy/_event.pyx", line 1138, in kivy._event.EventObservers._dispatch
   File "MineSweeper.py", line 37, in onPress
     self.revealNeighbors(self.loc[0],self.loc[1])
   File "MineSweeper.py", line 46, in revealNeighbors
     if self.app.root.ids.myboard.cells[i][j].visible != True:
   File "kivy/properties.pyx", line 863, in kivy.properties.ObservableDict.__getattr__
 AttributeError: 'super' object has no attribute '__getattr__'

1 个答案:

答案 0 :(得分:0)

问题1-KeyError和AttributeError:myboard

 Traceback (most recent call last):
   File "kivy/properties.pyx", line 860, in kivy.properties.ObservableDict.__getattr__
 KeyError: 'myboard'

根本原因

发生KeyError是因为在字典类型属性myboard中找不到self.ids

由于您的Kivy应用未使用kv文件,因此self.ids为空。

Kv language » self.ids

  

当解析您的kv文件时,kivy会收集所有标有的小部件   id,并将其放在此 self.ids 字典类型属性中。

解决方案

您的Kivy应用程序中存在一些问题。

修复1-KeyError和AttributeError:myboard

解决方案是使用ids在Python脚本中创建自己的self.ids.myboard = self

代码段-修复KeyError和AttributeError:myboard

class GameBoard(GridLayout):

    def __init__(self, **kwargs):
        super(GameBoard, self).__init__(**kwargs)
        self.ids.myboard = self    # create self.ids.myboard
        ...

修复2-AttributeError:MineSweeper

应用修订1后,应用崩溃,并显示以下AttributeError。

     self.app.ids.myboard.cells[i][j].visible = True
 AttributeError: 'MineSweeper' object has no attribute 'ids'

该应用程序类没有属性idsids仅存在于根对象中。

解决方法是使用App.get_running_app()获取应用程序的实例,并使用root.ids.myboard获取myboard的引用并将其保存到本地属性。

代码段-修复AttributeError:MineSweeper

def revealNeighbors(self, y, x):
    ...
                myboard = App.get_running_app().root.ids.myboard
                if myboard.cells[i][j].visible != True:
                    myboard.cells[i][j].visible = True
                    myboard.cells[i][j].text = myboard.cells[i][j].val
                    if myboard.cells[i][j].val == '0':
                        myboard.cells[i][j].revealNeighbors(myboard.cells[i][j], i, j)
    ...

修复3-TypeError:reveveNeighbors

应用修订1和2之后,应用崩溃,并出现以下TypeError。

     myboard.cells[i][j].revealNeighbors(myboard.cells[i][j], i, j)
 TypeError: revealNeighbors() takes 3 positional arguments but 4 were given

解决方法是通过ij

代码段-修复TypeError:recoverNeighbors

def revealNeighbors(self, y, x):
    ...
                myboard = App.get_running_app().root.ids.myboard
                if myboard.cells[i][j].visible != True:
                    myboard.cells[i][j].visible = True
                    myboard.cells[i][j].text = myboard.cells[i][j].val
                    if myboard.cells[i][j].val == '0':
                        myboard.cells[i][j].revealNeighbors(i, j)
    ...