2015-05-11 129 views
1

包含某些值的變量self.x只能在子類B中創建。抽象屬性的實現

這個變量用在父類A中,爲了確保我不會忘記實現它,我使用了@abstractproperty

此外,爲避免不必要地多次計算big_method(),我將值存儲在self.__x中,並返回該值。

import abc 


class A(metaclass=abc.ABCMeta): 

    @abc.abstractproperty 
    def x(self): 
     pass 

    def f(self): 
     print(self.x) 


class B(A): 

    def __init__(self): 
     self.__x = None 

    def big_method(self): 
     # Quite a bit of code here. 
     return 2 

    @property 
    def x(self): 
     # When called for the first time, it stores the value and returns it. 
     # When called later, the stored value is returned. 
     if self.__x: 
      pass 
     else: 
      self.__x = self.big_method() 

     return self.__x 

inst = B() 
inst.f() 

它按預期工作。

不過,我想知道是否有使用的abstractproperty,因爲我可以達到同樣的效果(即,越來越提醒實施self.x)任何真正的原因 ..不執行它在所有:
- 當視覺檢查代碼時,self.x將被我的IDE標記爲「警告」。
- 嘗試運行代碼時,我會得到一個AttributeError
- 最重要的是,我可以使用評論來確保我很容易理解爲什麼self.x未在A中實施。

另外,在B類中實施x的方法是否有更好的方法,即不需要多次重複評估big_method()

+1

我不知道我已經理解了你的問題,但是'B類(A):x = list(range(5))'應該做你想做的。 –

+0

@AndreaCorbellini我的不好,我不應該過分簡化'self .__ x'的評估方式。它實際上使用了B類的其他一些方法(以及A類和B類之間的另外10個類)。我會編輯以使其更清楚。 –

+0

同樣,我不確定我是否理解,但是試試這個:讓'B'從'object'繼承,並在代碼的末尾添加一個對'A.register(B)'的調用。 –

回答

1

定義x是一個抽象屬性阻止你寫這樣的代碼:

class A(metaclass=abc.Metaclass): 
    pass 

class B(A): 
    # Do stuff... 

inst = B(A) 
inst.x = "foo" 

在這裏,沒有什麼能阻止你從失敗中B定義x作爲一個屬性,然後實例化之後設置的值。對於抽象屬性,您至少需要默認值__set__才能使inst.x = "foo"正常工作。