2017-11-27 6 views
0

私は独自のバージョンのpygame.Rect矩形を作成しようとしていますが、正方形が特定のワールドバウンドから外れているときに、 。__getattr__(pygame.Rect)を使用するクラスを拡張する

これは私の拡張でpygame.Rectの多くの機能を書き直さなければならなかったことを意味し、それに成功しました。ここに問題はありません。

__getattr__と__setattr__を変更しようとすると問題が発生します。 pygame.Rectはこれらの関数を多用しているので、例えば 'top'や 'bottom'を求めると 'y'と 'y' + 'width'をそれぞれ参照します。私はこれらの関数を自分の機能に合わせて変更しましたが、もう一つ必要なことがあります: __init__関数では、worldwidthとworldheight変数を作成する必要があります。しかし、私はできません。なぜなら、__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.Rectのコードは似ています:__setattr__と__getattr__はworldwidthやworldheightを参照しませんが、そうでなければ同じですが、pygame.Rect .__ init__関数は非常に長いですが、以下のスニペットが最も重要です。

完全なコードは https://github.com/brython-dev/brython-pygame/blob/master/pygame/rect.py

で発見することができます

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])))) 

私は今取得エラーは次のとおりです。

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

明白な修正が__slots__、そこから行くことworldwidthとworldheightを追加しているようです。それはさらに奇妙な誤りをもたらしました。任意の変数を設定しようとしたときには、次のメッセージを与える:

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

だから要するに、私の質問は、つまるところ:なぜ私は新しい変数を作成することはできません、と私はできるように、私は、何をすべきかが必要ですか?

+0

スロットと '__setattr__'を使用する必要がありますか? 'self._worldwidth'は使えませんか? – furas

+0

スロットを使用する必要があるかどうかわかりません。私はそれを使用するクラスを拡張しようとしているので、同じスタイルを使用するのが理にかなっています。私は 'top'のような属性を保持したい場合は\ __ setattr__を使用する必要があります。私は 'self._worldwidth'を使うことができますが、これは\ __ setattr__関数では認識されず、AttributeError – user2424345

+0

を私は別のやり方でやっています。私は 'class Rectinworld(object):'の内部に 'self._r = Rect()'を作成し、 '@ property'を使用します。 – furas

答えて

0

私はそれが正しいかどうかはわかりませんが(Python 2および3の場合)
そしてそれはあなたが望むように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 
+0

ありがとう!これはホビープロジェクトなので、正しい解決策であるかどうかを実際にテストするには時間がかかるかもしれませんが、うまくいくようです。 – user2424345

関連する問題