-3

I get an error saying that the class Guitar doesn't have attribute "type", but it should inherit from super class Equipment.

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()

I did the same with the Equipment class, so I think it must be an inheritance thing.

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
  • 4
    1. Why do you initialise everything as a class attribute? 2. Why do all attributes have name-mangled double-underscore names? 3. Provide a [mcve] to replace the current code dump. – jonrsharpe Jul 24 '15 at 06:16
  • I followed a tutorial from YouTube where the guy used __ in his class attributes. – user3710863 Jul 24 '15 at 07:22
  • 1
    You should perhaps be a little more circumspect in your choice of learning materials! There are plenty of good Python tutorials out there, this doesn't appear to be one of them. – jonrsharpe Jul 24 '15 at 07:23
  • Yeah, I suspected something was amiss when he went through "the whole language" in one 40 minute video. – user3710863 Jul 24 '15 at 07:27

2 Answers2

1

When you define a variable in class with double underscore infront of the variable, and atmost one underscore at the end, it causes python to do Name Mangling at the time of definition of the class.

That is a name like - __type is converted to _<className>__type . From documentation -

Since there is a valid use-case for class-private members (namely to avoid name clashes of names with names defined by subclasses), there is limited support for such a mechanism, called name mangling. Any identifier of the form __spam (at least two leading underscores, at most one trailing underscore) is textually replaced with _classname__spam, where classname is the current class name with leading underscore(s) stripped.

Example to show this behavior -

>>> 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

Lets say example - __type, and after that you cannot access the variable outside the class using __type , and when it is inherited, it would be inherited as _<ClassName>__type .

Even during inheritence same rules apply,

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

But from the looks of it, not sure if you really need to define all the names in your clas such that Name mangling occurs. If you do not need name mangling to occur, remove the starting double underscore.


Also, when you define a variable directly inside a class, they become class variables, that is all instances share the same reference, until you set the reference for each instance to a different object (through assignment) . In your case, you do not need to define all the variables as class variables.

Anand S Kumar
  • 88,551
  • 18
  • 188
  • 176
0

You prefixed all your attribute names with two underscores. This triggers a name mangling mechanism that adds the class name to the attribute name, so child classes cannot override them. This is by design and is meant to avoid accidental overrides (kind of like a "private final" in Java)

So the solution here is to get rid of these underscores. Python has no real access restriction mechanism (the closer is the name mangling thing explained above) and relies on a simple naming convention: names with a single leading underscore are considered as "not part of the public api" (equivalent of a "protected" in other languages) so that's possibly what you want here.

This being said, you don't even need this here. Python has a strong support for computed attributes so you can as well remove all your getters/setters and use plain attributes instead, you'll always have the choice to turn them into computed ones latter if needed.

bruno desthuilliers
  • 75,974
  • 6
  • 88
  • 118