0

Here is something I tried in Python (2.7.9) shell (IDLE on Windows):

>>> class A:
    def bob(self, x):
        self.val = x*x

followed by:

>>> class B(A):
        def bob(self,x):
            flow = x*x*x
            A.bob(self, x)

and then:

>>> y = B()
>>> y.bob(4)
>>> y.val
16
>>> y.flow

Traceback (most recent call last):
  File "<pyshell#52>", line 1, in <module>
    y.flow
AttributeError: B instance has no attribute 'flow'

Question is, why is the method flow() undefined ? Looking around, I got the impression that perhaps the member variable might have to be initialized in init() during object construction phase, but that didn't help either.

bdutta74
  • 2,798
  • 3
  • 31
  • 54
  • By the way, the question you literally wrote is "why is the method flow() undefined". What it's complaining about is that the _attribute_ `flow` doesn't exist. And I'm pretty sure you expected a normal data attribute (a variable referring to the number 64), not a method there, right? – abarnert Apr 17 '15 at 06:53

2 Answers2

4

you're not assigning flow to the class instance

class B(A):
    def bob(self,x):
        flow = x*x*x  # should be self.flow
        A.bob(self, x)

more on scoping

Community
  • 1
  • 1
Hedde van der Heide
  • 21,841
  • 13
  • 71
  • 100
3

flow on its own is just a local variable, that lives as long as this method and then goes away.

self.flow is an instance variable. That's what you wanted.

(If you're coming from another language like C++ that has an implicit this/self for members... Python doesn't have that. Guido explains why, even with some clever ideas that make the historical reasons no longer relevant, Python still doesn't have that, and probably never will.)


As a side note, in Python 2.7, always use class A(object):, not class A:. Otherwise, you're creating old-style classes. That doesn't make a difference in this case, but in cases where it does make a difference, you always want the new behavior.*


Looking around, I got the impression that perhaps the member variable might have to be initialized in init() during object construction phase, but that didn't help either.

Well, first, it's __init__; a method just called init won't get called during object construction.

Anyway, usually you want to create all your attributes in __init__. (That's one easy way to guarantee that all instances of your type will have those members—unless you del them, of course…) But there's nothing requiring you to. In Python, you can add and delete attributes to an object at any time.**


* There are some cases where arguably you don't, but if you don't already know those cases and how to evaluated those arguments, they don't apply to you.

** Unless the class prevents you from doing so. Many builtin types do; you can do something similar yourself with __slots__; or you can even write a custom __setattr__ method that does anything you want.

abarnert
  • 354,177
  • 51
  • 601
  • 671