Python: how to reference member variables

I am learning Python at Codecademy and I am very confused. I cannot figure out how to access the member variables (I hope they are called). Here is a piece of code I wrote to demonstrate my confusion:

class Triangle(object):
    number_of_sides = 3

    def __init__(self, angle1, angle2, angle3):
        self.angle1 = angle1
        self.angle2 = angle2
        self.angle3 = angle3

    def check_angles(self):
        return self.angle1 + self.angle2 + self.angle3 == 180

class Equilateral(Triangle):
    angle = 60
    def __init__(self):
        self.angle1 = self.angle
        self.angle2 = self.angle
        self.angle3 = self.angle

      

So, in a subclass Equilateral angle1

, angle2

, angle3

are not included as parameters __init__

. However, the code below is __init__

reinitialized model

, color

and mpg

. Why is this? Shouldn't this just be inherited like in the above code with a subclass Equilateral

? I don't understand why they were written differently.

class Car(object):
    condition = "new"
    def __init__(self, model, color, mpg):
        self.model = model
        self.color = color
        self.mpg   = mpg

    def display_car(self):
        print "This is a %s %s with %s MPG." %(self.color, self.model, str(self.mpg))

    def drive_car(self):
        self.condition = "used"

class ElectricCar(Car):
    def __init__(self, model, color, mpg, battery_type):
        self.model = model
        self.color = color
        self.mpg   = mpg
        self.battery_type = battery_type

      

+3


source to share


3 answers


However, in the code below, init reinitializes the model, color and mpg. Why is this?

As the author ElectricCar

wants the user to be able to initialize ElectricCar

with four parameters.

ec = ElectricCar('xyz-500', 'blue', 0.5, 'boxy')

      

However, they had to pass arguments to the base class method __init__

:

class ElectricCar(Car):
    def __init__(self, model, color, mpg, battery_type):
        super(ElectricCar, self).__init__(model, color, mpg)
        self.battery_type = battery_type

      



In the case, EquilateralTriangle

all angles are the same and must be 60 degrees, so it doesn't make sense to initialize such an object from three custom angles.

The same comment about the base class __init__

applies:

class Equilateral(Triangle):
     angle = 60
     def __init__(self):
         super(Equilateral, self).__init__(Equilateral.angle,
                                           Equilateral.angle,
                                           Equilateral.angle)

      

Also note that there is no point in initializing Triangle

from three sides if you are talking about a space where the interior angles of a triangle are up to 180 degrees (or any fixed number). It would be more appropriate to transfer only two angles.

+3


source


Both implementations seem to be slightly disabled. In Python, the superclass __init__()

is not automatically called . You must explicitly do this.

Shouldn't this just be inherited like in the code above with the Equilateral subclass?

When instantiated Equilateral

, Triangle.__init__()

never called in the above implementation. There is no automatic initializer inheritance (this would violate PEP 20 : "Explicit is better than implicit").

Equilateral

it's probably better to read:

class Equilateral(Triangle):
     angle = 60
     def __init__(self):
         super(Equilateral, self).__init__(self.angle, self.angle, self.angle)

      



Same with ElectricCar

:

class ElectricCar(Car):
    def __init__(self, model, color, mpg, battery_type):
        super(ElectricCar, self).__init__(model, color, mpg)
        self.battery_type = battery_type

      

I don't understand why they were written differently.

This question is difficult to answer. The author either misunderstood how Python inheritance works, or he / she had a clear reason for not calling the superclass initializer.

+2


source


In Python, classes work like a bow. The outermost layer - this "instance" object self

. The layer below is a class object, itself is an instance. The layers below are class objects that are inherited from (base classes).

Put something in a class definition like number_of_sides

in Triangle

, puts something in a class object. The assignment self

puts something on an instance object, another onion layer.

When resolving the type name self.angle

, Python starts looking for the layer self

. If it isn't found there, it looks at the layer below, and so on. In the example, Equilatoral is angle

not found in self

, but it is in the class Equilatoral

. angle1

known only in an instance variable self

, not in a class variable Equilatoral

.

In the Car example, variables model

, color

and mpg

are stored in the instance, not in the class itself. They are created when a function is called Car.__init__

that is not inherited by any magic code. This is by design, as Python prefers explicitly hidden behavior. As juan explains, you must explicitly call the base class constructor to fully initialize the instance object.

At first, having to explicitly call basic constructors seems cumbersome, but in languages ​​that prefer implicit actions (like C ++ and its derivatives), you need all sorts of syntax nightmares to override implicit behavior explicitly. This is one of the reasons why Python has such a soft learning curve.

+1


source







All Articles