Monkey 补丁可以替换 class 中的现有函数定义吗?

Can Monkey patching replace existing function definition in a class?

我知道 SO 社区有多激烈,所以我会尽力保留问题 minimal, complete and verifiable

我只是想知道猴子补丁是否可以用来替换现有函数的定义?

例如:

class A():

    def foo():
       print '2'

def foo():
    print '5'

A.foo = foo

这种方式似乎也不起作用,为什么我不只是添加一个新函数而不是替换现有函数,我在其他 类 中调用这些函数,据我了解猴子补丁在 运行 时间添加了这些函数,我需要我的 python 代码到 Apache spark 服务器上的 运行,这会抛出一个错误,认为对该函数的调用未被引用。

所以请友好地帮助我或提出解决方法。 谢谢。

编辑: 代码的目标是在调用 A.foo 时打印 5。

我希望我明白你在这里想做什么。这适用于 Python 3:

class A():

  def foo():
     print('2')

def foo():
  A.foo = lambda: print('5')

A.foo() # Print '2'
foo()   # Assign the new method
A.foo() # Prints '5'

Python 2 但是有几个注意事项。

  • print 不是 Python 3 中的方法(参见此处:Why doesn't print work in a lambda?

  • 您不能只调用未绑定的消息(请参阅此处:In Python, can you call an instance method of class A, but pass in an instance of class B?

所以你必须这样做:

from __future__ import print_function

class A():

  def foo():
    print('2')

def foo():
  A.foo = lambda: print('5')

A.foo.__func__() # Print '2'
foo()   # Assign the new method
A.foo.__func__() # Prints '5'

编辑: 在评论中看到您的问题后,我认为您实际上想要一些不同的东西。这是哪个:

class A():

    def foo(self):
       print '2'

def foo(self):
  print '5'

a = A()
a.foo() # Print '2'
A.foo = foo   # Assign the new method
a.foo() # Prints '5'

这在 Python 2.

中工作得很好

self 是对该方法绑定到的当前实例的引用。当您只是调用 print 之类的东西来访问附加到该实例的任何属性或方法时,它不会被使用。但对于不同的情况,请查看以下示例:

class A():

    msg = "Some message"

    def foo(self):
       print self.msg


def bar(self):
  self.msg = "Some other message"

a = A()
a.foo() # Print old msg
A.bar = bar   # Assign the new method
a.bar() # Assigns new message
a.foo() # Prints new message

正如切普纳在他 post 下的评论中指出的那样:

The name self isn't special; it's just a convention. You could use this if you really wanted to, and it doesn't need to be the same name in both functions defined here. What is important is that the first argument to a function used as an instance method will be a reference to the calling object. a.foo() is almost exactly the same as A.foo(a)

您唯一的问题是您一开始就没有正确定义 foo。它需要为调用它的实例采用显式参数。

class A(object):
    def __init__(self)
        self.x = 2

    def foo(self):
        print(self.x)

def foo(this):
    print(this.x + 3)

A.foo = foo

a = A()
a.foo()  # outputs 5 in Python 2 and Python 3

在非常真实的意义上,猴子补丁是 类 最初的创建方式。 class 语句几乎只是以下代码的语法糖:

def foo(self):
    print(self.x)
A = type('A', (object,), {'foo': foo})
del foo

type 的定义想象成

并不过分简化
def type(name, bases, d):
    new_class = magic_function_to_make_a_class()
    new_class.name = name
    new_class.bases = bases
    for k, v in d.items():
        setattr(new_class, k, v)
    return new_class