【问题标题】:how do you attach a function to an instance of a class?如何将函数附加到类的实例?
【发布时间】:2021-12-31 00:42:48
【问题描述】:

我曾经在方案中编程: 在方案(一种函数式风格)中,函数是值。 您可以将函数附加到“结构”- python中类的方案等价物- 你能做类似的事情吗 与 python 类? 或者,换一种说法,你可以将函数传递给构造函数吗?

【问题讨论】:

  • object.attribute = somefunction
  • 函数也是 Python 中的一等值。
  • 类也是如此。
  • 除了类之外,您还可以将 Python 函数放入 dicts 中。这是一个相当常见的场景,并且是使用 Python 的 lambda 函数的好地方,如果您的函数不需要做任何复杂的事情。

标签: python class functional-programming


【解决方案1】:

答案是肯定的:函数是 Python 中的一等值,您可以将这些动态附加到类或类实例以创建方法。在类的情况下,这很简单,但在实例的情况下,这需要一些设置。

为了说明区别,请考虑以下代码:

class Hello:
    def say_hello(self):
        print("Hello")

print(type(Hello.say_hello))   # <class 'function'>
print(type(Hello().say_hello)) # <class 'method'>

你可以看到,对于同一个方法,从类中引用时是函数类型,从实例中引用时是方法类型。 (另外,函数和方法本身就是类;它一直是乌龟。)

要为类动态添加方法,使用常规函数就足够了。例如:

def say_hello(self):
    print(f"Hello, {self.name}!")

class Greeter:
    def __init__(self, name):
        self.name = name

Greeter.greet = say_hello
Greeter("Sir Robin").greet() # Prints "Hello, Sir Robin!"

但是,实例上的方法绑定到实例;这意味着当你调用instance.method() 时,Python 会自动为方法提供self 参数。对于普通类,Python 自己处理绑定,但是当您动态添加方法时不会发生这种情况。比如这段代码会报错:

def say_hello(self):
    print(f"Hello, {self.name}!")

class Greeter:
    def __init__(self, name):
        self.name = name

greeter = Greeter("Sir Robin")
greeter.greet = say_hello
greeter.greet() # TypeError: say_hello() missing 1 required positional argument: 'self'

相反,您必须自己绑定方法。这可以使用类型库中的MethodType 来完成。

import types

def say_hello(self):
    print(f"Hello, {self.name}!")

class Greeter:
    def __init__(self, name):
        self.name = name

greeter = Greeter("Sir Robin")
greeter.greet = types.MethodType(say_hello, greeter)
greeter.greet() # Prints "Hello, Sir Robin!"

警告:在 99% 的情况下,您最好只使用常规函数或类,因为动态分配方法通常不会在 Python 中完成,并且可能会使其他开发人员感到困惑。如果你真的需要动态查找,使用像__getattr__ 这样的魔术方法比动态方法绑定更常见。使用此技术需要您自担风险!

【讨论】:

    【解决方案2】:
    class MyClass:
       def my_method(self):
           print("Hello world!")
    

    通过使用my_object.my_method = my_functionMyClass.my_method = my_function,您可以动态添加它。但不鼓励这样做,因为它会使代码更难理解。

    编辑:要获得一个接收self arg 的绑定方法,您需要将它添加到类中。这也反映在现有实例上。如果直接将方法添加到实例中,调用时不会收到self

    【讨论】:

    • my_object 是一个实例时,my_object.my_method 是否真的像方法一样工作?在这种情况下,它似乎不会是绑定方法。
    • 是的,应该,但您必须附加一个至少接受 self 参数的函数。
    • 你应该测试一下。你会发现你可能需要使用types lib 并执行类似some_instance.some_function = types.MethodType( some_function, some_instance )
    • 经过测试,适用于 Python 3.9。实际上并不奇怪,方法调用处理并没有太多神奇之处(self 注入除外)。
    • 对不起,我看错了你的问题。我会更新答案以非常清楚
    猜你喜欢
    • 2012-12-24
    • 1970-01-01
    • 1970-01-01
    • 2023-03-05
    • 1970-01-01
    • 1970-01-01
    • 2015-04-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多