1

#for example:

class example(object):

    def someFunction():
        print("I am some function")

    def __init__(self,x,y):
        self.x = x
        self.y = y
        someFunction()

Why does this code generate the error that someFunction is not defined? Is it because python's interpreter executes the def init code block before it executes the def someFunction code? I thought python's order of execution was a top down approach. Any insight would be appreciated.

7alman
  • 157
  • 2
  • 3
  • 11
  • 4
    It's not quite clear to me what you are asking here. Did you intentionally leave out the `self` argument on `someFunction()`, and are wondering why `__init__()` can't see names from the enclosing scope? Or are you wondering what the correct way to call a method is? The answer to the latter question is Andy Hayden's answer below. The answer to the former question is a bit more involved. – Sven Marnach Jun 13 '16 at 19:43
  • Could you explain why __init__() can't see names from the enclosing scope, that's what I was trying to ask. – 7alman Jun 13 '16 at 19:46
  • 1
    Related: http://stackoverflow.com/questions/9505979/the-scope-of-names-defined-in-class-block-doesnt-extend-to-the-methods-blocks http://stackoverflow.com/questions/13937637/why-doesnt-class-start-a-new-scope-like-def-does – Sven Marnach Jun 13 '16 at 19:48
  • Exactly what I was looking for Sven, thank you – 7alman Jun 13 '16 at 19:56

2 Answers2

1

You need to prefix it with self too:

def __init__(self,x,y):
    self.x = x
    self.y = y
    self.someFunction()
Andy Hayden
  • 359,921
  • 101
  • 625
  • 535
  • 2
    And a `self` parameter on the method as well. – Sven Marnach Jun 13 '16 at 19:40
  • So, you can't call functions inside instance methods, that don't use the self parameter? – 7alman Jun 13 '16 at 19:41
  • @7alman this is python101 ... perhaps you should start with some tutorials on python classes ... if you are struggling with this, you will have even more problems later (example once you fix it to `self.someFunction()` you will probably find that you get an error about one argument being passed, but that the method does not except arguments – Joran Beasley Jun 13 '16 at 19:51
  • that's not the question being asked Joran, I know instance methods need the self argument passed, and they must be called on an instance, look at sven's comment above. – 7alman Jun 13 '16 at 19:56
  • @7alman no, you have to pass the self parameter (with self.XXX). Sven is correct though, someFunction should be defined as `def someFunction(self): ...` or `@staticmethod someFunction(): ...` – Andy Hayden Jun 13 '16 at 20:01
  • `x.method()` is equivalent to `x.__class__.method(x)`, if this helps. Also see my answer below. – holdenweb Jun 13 '16 at 20:37
0

Andy Hayden's answer gives you the necessary fix, but I thought you might appreciate a little more background specifically directed at your question. Note that this describes the so-called "new" object model, though the old model (from pre-2.2 days, and still the default in Python 2, operates pretty much the same).

When the interpreter compiles a class is reads the whole class body and saves the definitions (in your case, someFunction and __init__) in a dictionary. It builds a list of "base classes" (classes from which it inherits), and then it calls the class's metaclass (unless you take special action, in Python your classes' metaclass will be the built-in type type) with the class name, the list of base classes and the dict representing the class's namespace as arguments.

In Python 3, where the new model is the default, you can set the metaclass of a class using a keyword argument to the class declaration. This allows you to verify my assertion. Consider the following program:

class print_args(type):
    def __new__(cls, name, bases, name_space):
        print("class:", cls)
        print("Declaring class", name)
        print("Bases:", bases)
        print("Namespace:", name_space)
        return type.__new__(cls, name, bases, name_space)

class A: pass

class B: pass

print("Defining C")
class C(A, B, metaclass=print_args):
    CVar = "class attribute"
    def myMethod(self, a):
        return self.N, self.CVar
    def __init__(self, N):
        self.N = N
print("Creating c")
c = C(42)
print(c.CVar, C.CVar)
print(C.__dict__)
print(c.__dict__)
c.CVar = "instance attribute"
print(c.CVar, C.CVar)
print(c.__dict__)

The print_args class is a simple metaclass, that mimics the action of type by inheriting from it and delegating the real work to type.__new__ after a bit of printing. When the C class is declared, it outputs

Defining C
class: <class '__main__.print_args'>
Declaring class C
Bases: (<class '__main__.A'>, <class '__main__.B'>)
Namespace: {'__qualname__': 'C', '__module__': '__main__', '__init__': <function C.__init__ at 0x10778bbf8>, 'myMethod': <function C.myMethod at 0x10778bc80>, 'CVar': 'class attribute'}

Note that this all happens when the C class is declared - you can tell this by the next lines of output. Note also the values printed tell you what was passed to type.__new__. The program next creates a C instance, and demonstrates that the class attribute can also be accessed as an instance attribute - method resolution order is applied to attribute lookups too - in fact the instance could have also accessed attributes of the A and B classes had there been any.

Creating c
class attribute class attribute

At this point the __dict__ of class C looks like this:

{'CVar': 'class attribute',
 '__module__': '__main__',
 '__doc__': None,
 '__init__': <function C.__init__ at 0x10778bbf8>,
 'myMethod': <function C.myMethod at 0x10778bc80>}

and the dict of its instance looks like this:

{'N': 42}

It contains only the instance attribute N. But after a value is bound to c.CVar we can see that the instance attribute now differs from the class attribute.

instance attribute class attribute

This is confirmed by an updated look at the instance's __dict__.

{'CVar': 'instance attribute', 'N': 42}

Hopefully this will give you a bit more insight into what happens when you declare classes, and how the instances and the classes are related.

holdenweb
  • 33,305
  • 7
  • 57
  • 77