继承缺少属性

时间:2015-07-24 06:12:56

标签: python inheritance superclass super

我得到一个错误,说吉他类没有属性"键入",但它应该继承超级设备。

class Equipment(object):
    __id = 0
    __type = 0
    __brand = 0
    __model = 0
    __serialNumber = 0
    __purchaseCost = 0
    __hireCost = 0
    __available = 0

    def __init__(self, type, brand, model, serialNumber, purchaseCost, hireCost, available):
        self.__type = type
        self.__brand = brand
        self.__model = model
        self.__serialNumber = serialNumber
        self.__purchaseCost = purchaseCost
        self.__hireCost = hireCost
        self.__available = available

    def get_type(self):
        return self.__type
    def set_type(self,type):
        self.__type = type

    def get_brand(self):
        return self.__brand
    def set_brand(self,brand):
        self.__brand = brand

    def get_model(self):
        return self.__brand
    def set_model(self,model):
        self.__model = model

    def get_serialNumber(self):
        return self.__serialNumber
    def set_serialNumber(self,serialNumber):
        self.__serialNumber = serialNumber

    def get_purchaseCost(self):
        return self.__purchaseCost
    def set_purchaseCost(self,purchaseCost):
        self.__purchaseCost = purchaseCost

    def get_hireCost(self):
        return self.__hireCost
    def set_hireCost(self,hireCost):
        self.__hireCost = hireCost

    def get_available(self):
        return self.__available
    def set_available(self,available):
        self.__available = available

    def toString(self):
        return "type : {}, brand : {}, model : {}, serial number : {}, purchase cost : {}, hire cost : {}, available : {}".format(self.__type,
                                                        self.__brand,
                                                        self.__model,
                                                        self.__serialNumber,
                                                        self.__purchaseCost,
                                                        self.__hireCost,
                                                        self.__available)           
class Guitar(Equipment):
    __subtype = 0
    __bodyType = 0
    __pickupType = 0
    __tremSystem = 0

    def __init__(self, type, brand, model, serialNumber, purchaseCost, hireCost, available, subtype, bodyType, pickupType, tremSystem):
        super(Guitar, self).__init__(type, brand, model, serialNumber, purchaseCost, hireCost, available)
        self.__subtype = subtype
        self.__bodyType = bodyType
        self.__pickupType = pickupType
        self.__tremSystem = tremSystem


    def get_subtype(self):
        return self.__subtype
    def set_subtype(self, subtype):
        self.__subtype = subtype

    def get_bodyType(self):
        return self.__bodyType
    def set_bodyType(self, bodyType):
        self.__bodyType = bodyType

    def get_pickupType(self):
        return self.__pickupType
    def set_pickupType(self, pickupType):
        self.__pickupType = pickupType

    def get_tremSystem(self):
        return self.__tremSystem
    def set_tremSystem(self, tremSystem):
        self.__tremSystem = tremSystem

    def toString(self):
        return "type : {}, subtype : {}, brand : {}, model : {}, serial number : {}, purchase cost : {}, hire cost : {}, available : {}, body type : {}, pickup type : {}, trem system : {}".format(self.__type,
                                self.__subtype,
                                self.__brand,
                                self.__model,
                                self.__serialNumber,
                                self.__purchaseCost,
                                self.__hireCost,
                                self.__available,
                                self.__bodyType,
                                self.__pickupType,
                                self.__tremSystem)  

def main():
    type = input("please enter type: ")
    brand = input("please enter brand: ")
    model = input("please enter model: ")
    serialNumber = input("please enter serial number: ")
    purchaseCost = input("please enter purchase cost: ")
    hireCost = input("please enter hire cost: ")
    available = input("is item available: ")

    if type == "guitar":
        subtype = input("please enter subtype: ")
        bodyType = input("please enter body type: ")
        pickupType = input("please enter pickup config: ")
        tremSystem = input("please enter trem system: ")


    guitar = Guitar(type, brand, model, serialNumber, purchaseCost, hireCost, available, subtype, bodyType, pickupType, tremSystem)

    print(guitar.toString())

main()

我对Equipment类做了同样的事情,所以我认为它必须是继承的东西。

2 个答案:

答案 0 :(得分:1)

当你在类中使用变量的双下划线定义一个变量,并且在结尾处最多只有一个下划线时,它会导致python在定义类时执行 Name Mangling

这是一个名称 - __type转换为_<className>__type。来自documentation -

  

由于类私有成员有一个有效的用例(即为了避免名称与子类定义的名称冲突),对这种称为名称修改的机制的支持有限。表单__spam的任何标识符(至少两个前导下划线,最多一个尾随下划线)在文本上用_classname__spam替换,其中classname是当前的类名,其中前导下划线被剥离。

显示此行为的示例 -

>>> class CA:
...     def __init__(self):
...             self.__type = 1
...
>>> c = CA()
>>> c.__type
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'CA' object has no attribute '__type'
>>> c._CA__type
1

让我们说例子 - __type,之后你不能使用__type访问类外的变量,当它被继承时,它将被继承为_<ClassName>__type

即使在继承期间,也适用相同的规则,

>>> class BA(CA):
...     pass
...
>>> b = BA()
>>> b._CA__type
1

但从它的外观来看,不确定你是否真的需要在你的clas中定义所有名称,以便发生 Name mangling 。如果您不需要进行名称修改,请删除起始双下划线。

此外,当您直接在类中定义变量时,它们将成为类变量,即所有实例共享相同的引用,直到您将每个实例的引用设置为不同的对象(通过赋值)。在您的情况下,您不需要将所有变量定义为类变量。

答案 1 :(得分:0)

您使用两个下划线为所有属性名称添加前缀。这会触发名称修改机制,将类名添加到属性名称中,因此子类不能覆盖它们。这是设计上的,旨在避免意外覆盖(有点像Java中的“私人决赛”)

所以这里的解决方案是摆脱这些下划线。 Python没有真正的访问限制机制(更接近于上面解释的名称错误)并依赖于一个简单的命名约定:带有单个前导下划线的名称被视为“不属于公共API” (相当于其他语言中的“受保护”),这可能是你想要的。

话虽这么说,你甚至不需要这个。 Python对计算属性有很强的支持,因此您可以删除所有getter / setter并使用plain属性,如果需要,您可以随时选择将它们转换为计算属性。