简体   繁体   中英

Why do I keep getting this Attribute Error?

Every time I run my code it pops up the message saying "'ICU' object has no attribute '_name'. Did you mean: 'name'?" I can not figure out how to fix it. I've tried changing the name of the accessors and mutators but still can't figure out how to solve it. Any suggestions?

Here's my code:

class Patient:
    def __init__(self, name, age):
        self.name = name
        self.age = age
        self.weight = 150

    @property
    def age(self):
        return self._age

    @age.setter
    def age(self, newValue):
        if newValue > 0:
            self._age = newValue
        else:
            self._age = 0

    @property
    def weight(self):
        return self._weight


    @weight.setter
    def weight(self, newValue):
        if newValue >=0 and newValue <= 1400:
            self._weight = newValue


    #IncreaseAge
    def increaseAge(self):
        self.age = self.age + 1

class In(Patient):
    def __init__(self, name, age, stay):
        self.name = name
        self.age = age
        self.stay = stay

    @property  
    def stay(self):
        return self._stay

    @stay.setter
    def stay(self, value):
        self._name = value

    def __str__(self):
        print("IN-" + self._name + self._age + self.weight + self._stay)

class Out(Patient):
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __str__(self):
        print("OUT-" + self._name + self._age + self._weight)

class ICU(In):
    def __init__(self, name, age):
        self.name = name
        self.age = age
        self.days = 5 

class CheckUp(Out):
    def __init__(self, name, age):
        self.name = name
        self.age = age 

Here's the rest of the instance:

# Create three patient objects and print them out
p1 = ICU("Ben Dover", 0)
p2 = ICU("Helen Hywater", -15)
p3 = CheckUp("Amanda Lynn", 45)
p4 = ICU("Chester Minit", 12)
p5 = In("Don Keigh", 89, 10)
p6 = Out("Kay Oss ", 45)
print ("\tStatus\tName\t\tAge\tWeight\tStay")
print ("-" * 55)
print ("p1:\t{}".format(p1))
print ("p2:\t{}".format(p2))
print ("p3:\t{}".format(p3))
print ("p4:\t{}".format(p4))
print ("p5:\t{}".format(p5))
print ("p6:\t{}".format(p6))

print ("-" * 55)

# Change their ages and print them out
p1.age = -5
p2.age = 100
for i in range(6):
    p3.increaseAge()
p4.age = 0
p5.increaseAge()
p6.age = 42

print ("p1:\t{}".format(p1))
print ("p2:\t{}".format(p2))
print ("p3:\t{}".format(p3))
print ("p4:\t{}".format(p4))
print ("p5:\t{}".format(p5))
print ("p6:\t{}".format(p6))
print ("-" * 55)

# Change other instance variables and print them out
p1.weight = 2000
p1.stay = 3
p2.name = "Justin Thyme"
p2.weight = 220
p2.stay = 0
p3.weight = -50
p4.weight = 1400
p5.weight = 0
p5.stay = 21
p6.weight = 1401

print ("p1:\t{}".format(p1))
print ("p2:\t{}".format(p2))
print ("p3:\t{}".format(p3))
print ("p4:\t{}".format(p4))
print ("p5:\t{}".format(p5))
print ("p6:\t{}".format(p6))
print ("-" * 55)

It's because your variable name is different. Replace you code from:

@stay.setter
def stay(self, value):
    self._name = value

To:

@stay.setter
def stay(self, value):
    self.name = value

In Python, constructors - like all other methods - can be overridden. That is once you define __init__ in child classes, the base class method is never called. This is what's causing the error. You need to explicitly call the base class like like this:

class ICU(In):
    def __init__(self, name, age):
        self.name = name
        self.age = age
        self.days = 5 
        In.__init__(self, name, age, 10) # stay = 10 since it's not an input parameter in the ICU __init__ method.

This needs to be done in every base class. So you'd do something similar in the In class as well.

The problem comme to the fact that "format" is calling "__ str__" on your instances but when "__ str__" get called, some of your instance doesn't have a value for "_name" or "_stay" or "_weight"...see your " __ init __ " method for each instance and execute " __ str __" after you will see the problem. so to handle this case you have the following simple solution

 class In(Patient):
    def __init__(self, name, age, stay):
        self.name = name
        self.age = age
        self.stay = stay

    @property  
    def stay(self):
        return self._stay

    @stay.setter
    def stay(self, value):
        self._name = value

    def __str__(self):
        x = (
            getattr(self, '_name', ''),
            getattr(self, '_age', ''),
            self.weight or ''
            getattr(self, '_stay', ''),
        )
        return ("IN-%s %s %s %s")%(*x)


class Out(Patient):
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __str__(self):
        x = (
            getattr(self, '_name', ''),
            getattr(self, '_age', ''),
            getattr(self, '_stay', ''),
        )
        return "OUT- %s %s %s"%(*x)

But your classes are not well designed, see below something interesting

class Patient:
    def __init__(self, name, age,  weight=150):
        self._name= name
        self._age = age
        self._weight = weight

    @property
    def name(self):
        return self._name

    @name.setter
    def name(self, value):
        assert isinstance(value, str)
        self._name = value

    @property
    def age(self):
        return self._age

    @age.setter
    def age(self, value):
        assert isinstance(value, int)
        self._age = value

    @property
    def weight(self):
        return self._weight

    @weight.setter
    def weight(self, value):
        assert isinstance(value, int)
        self._weight = value

    def __str__(self):
        return f"{self.__class__.__name__.upper()}-{self.name} {self.age} {self.weight}"


class Out(Patient):
    pass

class In(Patient):
    def __init__(self, name, age, stay, weight=150):
        super().__init__(name, age, weight=weight)
        self._stay = stay

    @property
    def stay(self):
        return self._stay

    @stay.setter
    def stay(self, value):
        assert isinstance(value, int)
        self._stay = value

    def __str__(self):
        return f"{super().__str__()} {self.stay}"

class ICU(In):
    def __init__(self, name, age):
        super().__init__(name, age, 5)

class CheckUp(Out):
    def __init__(self, name, age):
        super().__init__(name, age)

Also note that "increaseAge" method is not defined on your instances

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM