Reputation: 2929
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:
turtle
- the instance of from my turtle
classturtle
classBut 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:
Person
class instance is age
, the only method birthday
raises the age by 1.jane
is Person
class instance, initialized at 20 years oldfoo
I am trying to call birthday
method on herbirthday
method and crashesSo, my question(s) is(are):
Thanks for those quick and nice answers! The additional question which naturally follows - is any of those ways preferred? I would guess, that
__getattribute__
and getattr
are pretty much the same, although for the first one, the inheritance is probably necessary.jane.birthday
or Person.birthday
, although in general it could be useful to be able to call the method for different Person
instances, e.g. created in the foo
function.Upvotes: 0
Views: 206
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
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
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
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