我对self._value继承后的来源感到困惑。父类仅具有self.value,而没有self._value
from abc import ABCMeta, abstractmethod
class Card(metaclass=ABCMeta):
def __init__(self, value):
self.value = value
@property
@abstractmethod
def value(self):
pass
@value.setter
@abstractmethod
def value(self, other):
pass
class BlackJackCard(Card):
def __init__(self, value):
super().__init__(value)
def is_ace(self):
return self._value == 1
def is_face_card(self):
"""Jack = 11, Queen = 12, King = 13"""
return 10 < self._value <= 13
@property
def value(self):
if self.is_ace() == 1:
return 1
elif self.is_face_card():
return 10
else:
return self._value
@value.setter
def value(self, new_value):
if 1 <= new_value <= 13:
self._value = new_value
else:
raise ValueError('Invalid card value: {}'.format(new_value))
但是,我运行了这段代码,发现可以通过构造函数分配的Foo实例化BlackJackCard类。 self._value == self.value == Foo。
但是父类 init 方法没有self._value ...
魔术在哪里?
答案 0 :(得分:1)
在def value(self, new_value)
方法上使用 @ value.setter 装饰器时,是在告诉Python使用该方法作为setter,这意味着只要{{1} }被调用。
因此self.value = something
构造函数调用BlackJackCard
构造函数,该构造函数表示Card
调用self.value = x
,后者依次执行value(self, x)
。因此,您的卡最终会将self._value = x
和value
属性都设置为_value
。
带有@装饰的示例:
x
输出:
class A(metaclass=ABCMeta):
def __init__(self, value):
print('constructing A')
self.x = value
class B(A):
def __init__(self, value):
print('constructing B')
super().__init__(value)
@property
def x(self):
print('getting x')
return self._internalX
@x.setter
def x(self, new_x):
print('setting x')
self._internalX = new_x
# test B
b = B('X')
print('b.x = "{}"'.format(b.x))
print('b._internalX = "{}"'.format(b._internalX))
没有@装饰器的反例:
constructing B
constructing A
setting x
getting x
b.x = "X"
b._internalX = "X"
输出:
class A(metaclass=ABCMeta):
def __init__(self, value):
print('constructing A')
self.x = value
class C(A):
def __init__(self, value):
print('constructing C')
super().__init__(value)
def x(self):
print('not getting x')
return self._internalX
def x(self, new_x):
print('not setting x')
self._internalX = new_x
# test C
c = C('X')
print('c.x = "{}"'.format(c.x))
try:
print('c._internalX = "{}"'.format(c._internalX))
except AttributeError as e:
print('oops:',e)