0

I saw this example from udacity.com :

def say_hi():
    return 'hi!'

i = 789

class MyClass(object):

    i = 5

    def prepare(self):
        i = 10
        self.i = 123
        print i

    def say_hi(self):
        return 'Hi there!'

    def say_something(self):
        print say_hi()

    def say_something_else(self):
        print self.say_hi()

output:

>>> print say_hi()
hi!
>>> print i
789
>>> a = MyClass()
>>> a.say_something()
hi!
>>> a.say_something_else()
Hi there!
>>> print a.i
5
>>> a.prepare()
10
>>> print i
789
>>> print a.i
123

I understand everything, except why a.say_something() equals hi! and not Hi there!. That is strange for me, because it calls say_something() which is inside the class when it calls say_hi() after that. Guess I missed something important..

DSM
  • 342,061
  • 65
  • 592
  • 494
Daniel
  • 1,562
  • 3
  • 22
  • 34

6 Answers6

5

Class scopes aren't considered when looking up a name in enclosing scopes. You should always qualify with self. to get a name from the class scope.

See The scope of names defined in class block doesn't extend to the methods' blocks. Why is that? for a more detailed discussion of this behaviour.

Community
  • 1
  • 1
Sven Marnach
  • 574,206
  • 118
  • 941
  • 841
  • But I thought python looks for an identifier in the local scope first, then in less local scope(and so on) and only then in the global scope. doesn't it ? – Daniel Sep 15 '12 at 16:22
  • @Daniel: Yes, except for that it skips class scopes, for the reasons discussed in the linked thread. – Sven Marnach Sep 15 '12 at 16:24
1

Consider the following code:

class X:
  def __init__(self, name):
    self.name = name
  def bound_method(self):
    print "I'm bound to", self.name
  @staticmethod
  def unbound_method():
    print "I have no self!"

x = X("Peter")
x.bound_method()   # prints: I'm bound to Peter
x.unbound_method() # prints: I have no self!

Class members and member functions in Python are variables and callables that are bound to an object of the class. These bound methods receive the object they are called with as their first call parameter, that is usually named self. Referring to bound methods and variables needs to be done explicitly, as in x.bound_method(). The object x is thereby turned into the first function argument self. If you want to access its members, you need to query self inside the function.

There are also class methods in Python. That is functions that are not bound to a specific instantiation, but are static to the class, see unbound_method() for an example.

moooeeeep
  • 31,622
  • 22
  • 98
  • 187
0

It's because a.say_something() doesn't call class method (it doesn't have self. part so it calls global function).

Konrad Borowski
  • 11,584
  • 3
  • 57
  • 71
0

in python to call inner class method you should write self. before method name, self. means that search class for this method but you don't use self when you call say_hi() in say_something method and this cause to call say_hi function that declared outside of class.
write this to solve problem.

def say_something(self):
    print self.say_hi()
Farnabaz
  • 4,030
  • 1
  • 22
  • 42
0

It's calling say_hi from the global scope, rather than the class scope because, within the class scope, there's no such function as say_hi, only self.say_hi

Maybe this will help:

name = 'John'
class Person()

    def __init__(self)
      name = 'Abraham'

    def printName(self)
      print name

>>> pers  = Person()
>>> pers.printName()
   'John'  # uses global name, rather than Abraham, 
           # because Abe is not a class instance variable.
sks-15
  • 147
  • 11
TankorSmash
  • 12,186
  • 6
  • 68
  • 106
0

Maybe this example will make more sense:

def global_scope_hi():
    return 'hi!'

class MyClass(object):

    def class_scope_hi(object_reference):
        return 'Hi there!'

    def say_something(object_reference):
        print global_scope_hi()

    def say_something_else(object_reference):
        print object_reference.class_scope_hi()

a = MyClass()
a.say_something()
a.say_something_else()

>>> hi!
>>> Hi there!
Steven Almeroth
  • 7,758
  • 2
  • 50
  • 57