quapka
quapka

Reputation: 2929

How to pass method into function outside the Class?

I might be missing something stupid, or I am simply trying to walk through a steel wall instead of going around. Basically I have created turtle class and I use it in different script for drawing L-systems. I thought I could create a function outside the turtle class, which will accept:

But it all crashes on trying to pass the method to the function - I think it does not see the method, since it is defined inside the class. To simplify the matters I have created a basic example, which fails at the same place:

class Person():
    def __init__(self, age):
        self.age = age


    def birthday(self):
        self.age += 1

def foo(person, method):

    person.method()

jane = Person(20)
foo(jane, birthday)

#Traceback (most recent call last):
#  File "passmethod.py", line 14, in <module>
#    foo(jane, birthday)
#NameError: name 'birthday' is not defined

That is:

So, my question(s) is(are):

Update

Thanks for those quick and nice answers! The additional question which naturally follows - is any of those ways preferred? I would guess, that

Upvotes: 0

Views: 206

Answers (4)

jonrsharpe
jonrsharpe

Reputation: 122090

As I suggested in the comments, you could sub-class your Turtle to add a rule-following method. To demonstrate a trivial example:

class InstructableTurtle(Turtle):

    def follow_instructions(self, instructions):
        for instruction in instructions:
            if instruction == "MOVE_LEFT":
                self.move_left()
            ...

But you could also have the rules provided as an additional argument to the new instance:

def __init__(self, ..., rules): # '...' represents args to base Turtle 
    super().__init__(...) # or 'super(InstructableTurtle, self)' on Python 2.x
    self.rules = rules 

As an example:

>>> class Turtle():
    def __init__(self, name):
        self.name = name
    def move_left(self):
        print("{0.name} is moving left...".format(self))


>>> class InstructableTurtle(Turtle):
    def __init__(self, name, rules):
        super().__init__(name)
        self.rules = rules
    def follow_instruction(self, instruction):
        self.rules[instruction](self)


>>> tommy = InstructableTurtle("Tommy", {"LEFT": Turtle.move_left})
>>> tommy.follow_instruction("LEFT")
Tommy is moving left...

Upvotes: 1

daouzli
daouzli

Reputation: 15328

You can use the __getattribute__ method (inherited from object):

class Person(object):
    def __init__(self, age):
        self.age = age

    def birthday(self):
        self.age += 1

def foo(person, method):
    person.__getattribute__(method)()

jane = Person(20)
foo(jane, "birthday")

Upvotes: 1

Tok Soegiharto
Tok Soegiharto

Reputation: 329

Here the working code:

class Person():
    def __init__(self, age):
        self.age = age


    def birthday(self):
        self.age += 1

def foo(person, method):

    getattr(person, method)()

Test:

>>> 
>>> jane = Person(20)
>>> foo(jane, 'birthday')
>>> jane.age
21
>>> 

Upvotes: 2

Tigran Saluev
Tigran Saluev

Reputation: 3582

Well, there are ways to do that.

First way: just pass method bound to a particular object:

def foo(person, method):
    method() # calls jane.birthday()

jane = Person(20)
foo(jane, jane.birthday)

Second way: pass a class method and apply it to a particular object:

def foo(person, method):
    method(person) # calls Person.birthday(jane), which is the same thing

jane = Person(20)
foo(jane, Person.birthday)

Upvotes: 1

Related Questions