2015-05-11 81 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"正常工作。