如何将方法传递到类外的函数?

时间:2014-06-18 09:03:23

标签: python

我可能会错过一些愚蠢的东西,或者我只是想通过钢墙走过而不是四处走走。基本上我创建了turtle类,我在不同的脚本中使用它来绘制L系统。我想我可以在 turtle 之外创建一个函数,它将接受:

  • turtle - 来自我的turtle
  • 的实例
  • 来自L-system的字符串
  • 规则字典/如何解释上面字符串中不同符号的说明,即符号调用来自turtle
  • 的方法

但是这一切都在试图将方法传递给函数时崩溃了 - 我认为它没有看到方法,因为它是在类中定义的。为了简化我创建的基本示例,它在同一个地方失败了:

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

那是:

  • Person类实例中唯一的变量是age,唯一的方法是birthday将年龄提高1。
  • janePerson类实例,初始化为20岁
  • by函数foo我试图在她的
  • 上调用birthday方法
  • 脚本未看到birthday方法并崩溃

所以,我的问题是(是)

  • 有办法吗,怎么办?如果是这样,怎么样?
  • 如果没有,或者不建议这样做,我应该使用什么?

更新

感谢那些快速而美好的答案!自然遵循的附加问题 - 是否有任何优先选择?我猜,那是

  • __getattribute__getattr几乎相同,但对于第一个,继承可能是必要的。
  • 在使用jane.birthdayPerson.birthday之间,我看不出在这种情况下有任何重大差异,但一般来说,能够调用不同Person实例的方法,例如在foo函数中创建。

4 个答案:

答案 0 :(得分:2)

这是工作代码:

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


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

def foo(person, method):

    getattr(person, method)()

测试:

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

答案 1 :(得分:1)

嗯,有办法做到这一点。

第一种方法:只传递绑定到特定对象的方法:

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

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

第二种方式:传递一个类方法并将其应用于特定对象:

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

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

答案 2 :(得分:1)

您可以使用__getattribute__方法(继承自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")

答案 3 :(得分:1)

正如我在评论中建议的那样,您可以对Turtle进行细分,以添加规则跟踪方法。为了演示一个简单的例子:

class InstructableTurtle(Turtle):

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

但您也可以将rules作为新实例的附加参数提供:

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

举个例子:

>>> 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...