简体   繁体   English

如何将 function 附加到 class 的实例?

[英]how do you attach a function to an instance of a class?

I used to program in scheme: in scheme (a functional style), functions are values.我曾经在方案中编程:在方案(一种函数式风格)中,函数就是值。 you can attach a function to a "struct"- the scheme equivalent of a class in python- can you do something similar with python classes?您可以将 function 附加到“结构”-python 中 class 的等效方案-您可以使用 python 类做类似的事情吗?

The answer is yes: functions are first-class values in Python, and you can attach these dynamically to classes or objects to make methods.答案是肯定的:函数是 Python 中的一等值,您可以将这些动态附加到类或对象以创建方法。 In the case of classes this is trivial, but in the case of objects this requires a bit of setup.在类的情况下,这是微不足道的,但在对象的情况下,这需要一些设置。

To illustrate the difference, consider the following code:为了说明差异,请考虑以下代码:

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

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

You can see that for the same method, when it is referenced from the class it is a function type, and when it is referenced from the instance it is a method type.您可以看到,对于相同的方法,当它从 class 引用时,它是 function 类型,而当它从实例引用时,它是方法类型。 (Also, functions and methods are themselves classes; it's turtles all the way down.) (此外,函数和方法本身就是类;它一直是乌龟。)

To dynamically add methods to classes, it it suffices to use regular functions.要为类动态添加方法,使用常规函数就足够了。 For example:例如:

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!"

However, methods on instances are bound to the instance;但是,实例上的方法绑定到实例; this means that when you call instance.method() , Python supplies the self argument to the method automatically.这意味着当您调用instance.method()时,Python 会自动将self参数提供给该方法。 For normal classes Python handles the binding itself, but this does not happen when you add methods dynamically.对于普通类 Python 处理绑定本身,但是当您动态添加方法时不会发生这种情况。 For example, this code will result in an error:例如,此代码将导致错误:

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'

Instead you have to bind the method yourself.相反,您必须自己绑定该方法。 This can be done using MethodType from the types library.这可以使用类型库中的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!"

Caveat: In 99% of cases you will be better off just using regular functions or classes, as dynamically assigning methods is not usually done in Python and will likely confuse other developers.警告:在 99% 的情况下,最好只使用常规函数或类,因为在 Python 中通常不会动态分配方法,并且可能会使其他开发人员感到困惑。 If you really need dynamic lookup, it is much more common to use magic methods like __getattr__ than dynamic method binding.如果您确实需要动态查找,则使用__getattr__之类的魔术方法比动态方法绑定更常见。 Use this technique at your own risk!使用此技术需要您自担风险!

class my_class:
   def my_method(self):
       print("Hello world!")

or或者

By using my_object.my_method = my_function or my_class.my_method = my_function you can add it dynamically.通过使用my_object.my_method = my_functionmy_class.my_method = my_function ,您可以动态添加它。 But this is discouraged, since it makes the code harder to understand.但这是不鼓励的,因为它使代码更难理解。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM