2014-04-16 60 views
1

運行這個程序只有一個成員被修改時,Pygame矩形的所有成員變量是如何更新的?

import pygame 
pygame.init() 

r = pygame.Rect((0, 0), (100, 100)) 
r.center = (455, 455) 

print r 

<rect(405, 405, 100, 100)>作爲輸出。如果我要檢查其他屬性,如topleftmidbottomcentery,它們也會被更新。

這是非常有用的,但我不知道這是如何完成的。我直接更新成員而不使用Rect類的任何成員函數。 Python是否有某種「鉤子」,可以在每次更新類的成員變量時執行?我可以用我自己的課程做這個,或者這是Pygame使用的特殊技巧?

回答

3

該文檔調用這些虛擬屬性。

在C代碼拼成的矩形類,左上看起來是這樣的:

/*topleft*/ 
static PyObject* 
rect_gettopleft (PyRectObject *self, void *closure) 
{ 
    return Py_BuildValue ("(ii)", self->r.x, self->r.y); 
} 

static int 
rect_settopleft (PyRectObject *self, PyObject* value, void *closure) 
{ 
    int val1, val2; 
    if (!TwoIntsFromObj (value, &val1, &val2)) 
    { 
     RAISE (PyExc_TypeError, "invalid rect assignment"); 
     return -1; 
    } 
    self->r.x = val1; 
    self->r.y = val2; 
    return 0; 
} 

... AMND這樣topright ...

/*topright*/ 
static PyObject* 
rect_gettopright (PyRectObject *self, void *closure) 
{ 
    return Py_BuildValue ("(ii)", self->r.x+self->r.w, self->r.y); 
} 

static int 
rect_settopright (PyRectObject *self, PyObject* value, void *closure) 
{ 
    int val1, val2; 
    if (!TwoIntsFromObj (value, &val1, &val2)) 
    { 
     RAISE (PyExc_TypeError, "invalid rect assignment"); 
     return -1; 
    } 
    self->r.x = val1-self->r.w; 
    self->r.y = val2; 
    return 0; 
} 

正如你可以看到rect_gettopright它是在飛行中生成的;它會添加self->r.xself->r.w以返回右上角右側「x」值的總值。

基本上,是的,他們是方便掛鉤。

編輯:一個可以做一個pure Python版本的使用性能:

class PyRect(object): 
    def __init__(self, x, y, w, h): 
     self.x = x 
     self.y = y 
     self.w = w 
     self.h = h 
     self._topright = None 
    @property 
    def topright(self): 
     if self._topright is None: 
      self._topright = (self.x + self.w, self.y) 
     return self._topright 
    @topright.setter 
    def topright(self, newx, newy): 
     self.x = newx - self.w 
     self.y = newy 
     self._topright = (newx, newy) 

這是真的快速和骯髒的,但它具有相同的整體效果。

+0

優秀的答案,以及通過C代碼挖掘的積分。 – pedram