扩展使用\uu getattr\uu的类(pygame.矩形)

2024-04-27 00:09:25 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试创建自己版本的pygame.矩形矩形,但有一个附加功能,即当一个正方形超出一定的世界范围时,它会出现在另一边。你知道吗

这意味着我必须重写pygame.矩形在我的扩展中,我成功了。这里没问题。你知道吗

当我尝试更改getattr和setattr时,问题就开始了。pygame.矩形大量使用这些函数,例如,要求'top'或'bottom'分别指'y'和'y'+'width'。我已经更改了这些功能以适应我的功能,但我还需要做一件事: 在初始化函数中,我需要创建worldwidth和worldwidth变量。但是我不能,因为setattr函数不允许。你知道吗

以下是我现在的情况:

class Rectinworld(pygame.Rect):
    '''hides the fact that the world is round, when it comes to collisions and such'''

    __slots__ = ['_r']

    def __init__(self,(worldwidth,worldheight),*args):
        object.__setattr__(self, "worldwidth",worldwidth)
        if len(args)==0:
            super(Rectinworld, self).__init__((0,0,0,0))
        else:
            super(Rectinworld, self).__init__(*args)

def __getattr__(self, name):
    if name == 'top':
        return self._r.y
    #etc etc etc
    elif name == 'height':
        return self._r.h
    else:
        raise AttributeError(name)

def __setattr__(self, name, value):
    if name == 'top' or name == 'y':
        self._r.y = value % worldheight
    #etc etc etc
    elif name == 'height':
        if int(value) < 0:
            self._ensure_proxy()
        self._r.h = int(value)
    else:
        raise AttributeError(name)

为了清晰起见,我在#etc etc etc注释中遗漏了一些代码。的代码pygame.矩形类似于:setattr和getattr并不引用worldwidth或worldwidth,但在其他方面是相同的pygame.矩形.\uu init\uuu函数非常长,但我认为下面的代码片段涵盖了最重要的部分:

def __init__(self, *args):
#etc etc etc
if len(args) == 4:
            if args[2] < 0 or args[3] < 0:
                object.__setattr__(self, '_r', _RectProxy((int(args[0]),
                                                          int(args[1]),
                                                          int(args[2]),
int(args[3]))))

完整的代码可以在https://github.com/brython-dev/brython-pygame/blob/master/pygame/rect.py找到

我现在得到的错误是:

line 10, in __init__
    object.__setattr__(self, "worldwidth",0)
AttributeError: 'Rectinworld' object has no attribute 'worldwidth'

一个明显的解决办法似乎是将worldwidth和worldheight添加到槽中,然后从那里开始。这就产生了更奇怪的错误。当试图设置任何变量时,它将给出以下消息:

line 65, in __getattr__
    raise AttributeError(name)
AttributeError: _r

所以简言之,我的问题归结为:为什么我不能创建新的变量,我需要做什么,这样我才能?你知道吗


Tags: 函数nameselfifinitetcargspygame
1条回答
网友
1楼 · 发布于 2024-04-27 00:09:25

我不确定它是否正确,但它适合我(在Python2和Python3上)
它使用slots如您所愿。你知道吗

import pygame

class Rectinworld(object):

    '''hides the fact that the world is round, when it comes to collisions and such'''

    __slots__ = ['_r', '_worldwidth', '_worldheight']

    def __init__(self, worldwidth, worldheight, *args):
        if not args:
            args = (0,0,0,0)

        super(Rectinworld, self).__setattr__("_r", pygame.Rect(args))
        super(Rectinworld, self).__setattr__("_worldwidth", worldwidth)
        super(Rectinworld, self).__setattr__("_worldheight", worldheight)

    def __getattr__(self, name):
        if name == 'top':
            return self._r.y
        #etc etc etc
        elif name == 'height':
            return self._r.h
        else:
            raise AttributeError(name)

    def __setattr__(self, name, value):
        if name == 'top' or name == 'y':
            self._r.y = value % self._worldwidth
        #etc etc etc
        elif name == 'height':
            if int(value) < 0:
                self._ensure_proxy()
            self._r.h = int(value)
        else:
            raise AttributeError(name)

#  - test  -

r = Rectinworld(100, 100)
r.top = 120
print(r.top) # gives 20

相关问题 更多 >