2017-11-27 13 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__ 함수가 매우 길지만 다음 코드 단편이 가장 중요하다고 생각합니다.

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' 

명백한 수정 __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

올바른지 확실하지 않지만 파이썬 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