Python - Kivy:AttributeError:'super'对象在尝试获取self.ids时没有属性'__getattr__'

2022-01-15 00:00:00 python kivy kivy-language

问题描述

我为一种 android lock 编写了一个代码,每当我尝试使用 id 获取特定的 ClickableImage 时,它​​都会引发以下错误:

I wrote a code for a kind of android lock thing, whenever I try to get an specific ClickableImage using the id it raises the following error:

AttributeError: 'super' object has no attribute '__getattr__'

我花了几个小时试图寻找这个问题的解决方案,我查看了其他有同样问题的人,人们告诉他们更改构建器的站点,因为需要首先调用它来获取 id属性或类似的东西,但每次我移动构建器时,它都会引发错误类未定义".有什么线索吗?

I've spent hours trying to look for a solution for this problem, I looked other people with the same issue, and people told them to change the site of the builder, because it needed to be called first to get the ids attribute or something like that, but everytime I move the builder, it raises the error "class not defined". Any clues?

这是我的代码:

from kivy.app import App
from kivy.config import Config
from kivy.lang import Builder
from kivy.graphics import Line
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.widget import Widget
from kivy.uix.image import Image
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.behaviors import ButtonBehavior

#Variables
cords = ()
bld = Builder.load_file('conf.kv')

class Manager(ScreenManager): pass
class Principal(Screen): pass

class ClickableImage(ButtonBehavior, Image):
    def on_press(self):
        self.source = 'button_press.png'

    def on_release(self):
        self.source = 'button.png'
        self.ids.uno.source = 'button_press.png'

class canva(Widget):
    def on_touch_down(self, touch):
        global cords
        with self.canvas:
            touch.ud['line'] = Line(points=(touch.x, touch.y), width=1.5)
        cords = (touch.x, touch.y)

    def on_touch_move(self,touch):
        global cords
         touch.ud['line'].points = cords + (touch.x, touch.y)

    def on_touch_up(self,touch):
        self.canvas.clear()

class Api(App):    
    def build(self):
        return bld

if __name__ == '__main__':
    Api().run()

这是我的 .kv 文件:

and here is my .kv file:

# conf to file:  test.py

<Manager>:
    Principal:

<Principal>:
    GridLayout:
        size_hint_x: 0.5
        size_hint_y: 0.6
        width: self.minimum_width
        cols: 3
        ClickableImage:
            id: 'uno'
            size: 10,10
            source: 'button.png'
            allow_strech: True
        ClickableImage:
            id: 'dos'
            size: 30,30
            source: 'button.png'
            allow_strech: True
    canva:


解决方案

让我们看看输出:

'super' object has no attribute '__getattr__'

在kv语言中,id是用特殊方式设置的(现在到1.9.2),它的值不是字符串,因为它不是一个随便的变量.您无法使用 <widget>.id 访问它.

In kv language id is set in a special way(up to 1.9.2 now), its value is not a string, because it's not a casual variable. You can't access it with <widget>.id.

我会说它类似于 canvas,它不是一个小部件,但它可能看起来像那样(这就是我对你的代码感到困惑的原因:P).您已经注意到 something: <some object> 就像 Python 的 something = <object> 并且(至少我认为)这就是 id 的值不是字符串(这对某些人来说很奇怪).如果 id 是一个字符串,则可能需要进行检查以以某种方式将其排除在临时分配值之外.也许是因为性能或只是简单.

I'd say it's similar to canvas, which is not a widget, yet it may look like that(which is why I was confused by your code :P). You've already noticed something: <some object> is like Python's something = <object> and that's (at least what I think) is the whole point of id's value not being a string(which to some is odd). If id was a string, there'd probably be needed a check to exclude it somehow from casual assigning values. Maybe it's because of performance or just simplicity.

因此,假设 id 是未来关键字的关键字.其实是这样,因为分配给id的字符会变成一个字符串key,其值为从WeakProxy得到的object,指向WeakProxy指向的object.或者说得更好:

Therefore let's say id is a keyword for a future keyword. In fact, it is, because the characters assigned to id will become a string key with a value of object got from WeakProxy, to the object WeakProxy points to. Or better said:

id: value

变成

<some_root_widget>.ids[str(value)] = weakref.proxy(value)

value 变成 object(print(self) 会返回什么)

where value becomes an object(what print(self) would return)

我怀疑(不确定)如果你使用字符串作为 id 的值,你最终会得到 weakref/WeakProxy 指向一个细绳.我使用 point 这个词,因为它提醒我指针,不要与 C 指针混淆.

I suspect(not sure) that if you use string as the value for id, you'll end up with weakref / WeakProxy pointing to a string. I use the word point as it reminds me pointers, don't get confused with C pointers.

现在如果你再看一下输出:

Now if you look again at the output:

  • super 让您可以访问您继承自的类

  • super gives you an access to a class you inherit from

print('string id'.__getattr__) 会给你同样的错误,但是 'super' 被替换为实际值,因为很好... 它没有 __getattr__

print('string id'.__getattr__) will give you the same error, but 'super' is substituted with the real value, because well... it doesn't have __getattr__

因此如果你给id赋值一个string值,你会遇到这种情况:

Therefore if you assign a string value to id, you'll get into this situation:

<some_root_widget>.ids[str('value')] = weakref.proxy('value')  # + little bit of magic

虽然 str('value') 不一定是错的,但默认情况下你不能为字符串创建 weakref.proxy.我不确定 Kivy 是如何使用 Wea​​kProxies 处理这个问题的,但是如果你给 id 分配一个字符串,大致就是这样.

Although str('value') isn't necessarily wrong, by default you can't create weakref.proxy for a string. I'm not sure how Kivy handles this with WeakProxies, but if you assign a string to id, roughly this is what you get.

(如有错误请指正)

相关文章