0

Method Eval in Child class inherits from Parents class; method FirstOrder in Child class calls method Eval in Child class. Codes:

class Parents:
     def Eval(self, x):
         return value, grad

class Child(Parents):
     def Eval(self, x):
         super(Child, self).Eval(x)

     def FirstOrder(self, x, x0):
         val, grad = self.Eval(x0)
         return val + grad * (x-x0)

and get:

TypeError: cannot unpack non-iterable NoneType object

I know an easy solution is to change self.Eval(x0) to super(Child, self).Eval(x0). But I want to know why. From my understanding, calling self.Eval(x0) in FirstOrder will lead to the definition of method Eval in Child class. Since it is well-defined, then it calls Eval in Parents class.

  • 2
    you forgot to `return` from `Eval` in `Child` – Robin Zigmond Mar 24 '21 at 20:16
  • @RobinZigmond Appreciate so fast a reply! I am new to python. So the `return` from `Eval` in `Child` cannot inherit from the `return` in `Parents` by `super`? – Silentmovie Mar 24 '21 at 20:18
  • I just mean that `super(Child, self).Eval(x)` should have a `return` in front of it. You need to return the result of the `super` call, otherwise the child method will implicitly return `None`. – Robin Zigmond Mar 24 '21 at 20:22
  • 1
    @Silentmovie "return" doesn't inherit. That *doesn't make any sense*. Inheritance applies to *attributes of objects*. In `Child.Eval`, you simply call `super(Child, self).Eval(x)`, which evalutates to whatever `value, grad` is, but you don't do anything with that return value, then the function terminates and returns `None` by default – juanpa.arrivillaga Mar 24 '21 at 20:59
  • This isn't really inheritance, it's more like delegating. @juanpa I'm pretty sure `Child.Eval` is redundant, right? and it'd be easier to inherit `Parents.Eval`? – wjandrea Mar 25 '21 at 00:01
  • Also, beside the point, but *UpperCamelCase* should be reserved for class names. For methods, use *snake_case*, i.e. `Parents.eval` and `Child.first_order`. Although note that `eval` is a builtin, so [you might want to use a different name](https://stackoverflow.com/q/9109333/4518341), like `eval_`. – wjandrea Mar 25 '21 at 00:06
  • @wjandrea Thanks for your follow-up and reminder the naming issue. `eval` is just an example but it is good to know that it is a builtin. – Silentmovie Mar 25 '21 at 03:44

1 Answers1

0

You're not returning anything from Child.Eval(), so it returns None implicitly. You just need to add return:

def Eval(self, x):
     return super(Child, self).Eval(x)

However, this isn't inheritance, it's delegation. Using inheritance would mean simply not defining Child.Eval(). And in fact, that's the better option since Child.Eval() doesn't do anything additional.

wjandrea
  • 28,235
  • 9
  • 60
  • 81