我可以替换Python中对象的现有方法吗?
Q:在Python(3.6)中有没有办法改变现有对象的方法?(所谓“方法”是指作为参数传递的函数。)我可以替换Python中对象的现有方法吗?,python,python-3.x,methods,Python,Python 3.x,Methods,Q:在Python(3.6)中有没有办法改变现有对象的方法?(所谓“方法”是指作为参数传递的函数。) 示例 假设我有一个类Person有一些非常有用的方法SayHi(): 如您所见,此人的反应取决于其当前情绪,该情绪由方法HasGoodMood()计算得出。当一个违约的人身上有超过10美元的现金时,他就会有好心情 我可以很容易地创造出一个不在乎金钱、一直快乐的人: >>> joe.HasGoodMood = lambda: True >>> joe.SayH
示例 假设我有一个类
Person
有一些非常有用的方法SayHi()
:
如您所见,此人的反应取决于其当前情绪,该情绪由方法HasGoodMood()
计算得出。当一个违约的人身上有超过10美元的现金时,他就会有好心情
我可以很容易地创造出一个不在乎金钱、一直快乐的人:
>>> joe.HasGoodMood = lambda: True
>>> joe.SayHi()
Hello!
>>> joe.Cash = 0
>>> joe.SayHi()
Hello!
酷。请注意,Python如何知道,当使用原始的HasGoodMood
实现时,它以静默方式传递self
作为第一个参数,但是如果我将其更改为lambda:True
,它将调用不带参数的函数。问题是:如果我想将默认值HasGoodMood
更改为另一个也接受self
作为参数的函数,该怎么办
让我们继续我们的例子:如果我想创造一个贪婪的人
,他只有在身上有超过100美元的钱时才会快乐,那该怎么办?我想做一些类似的事情:
>>> greedy_jack = Person()
>>> greedy_jack.HasGoodMood = lambda self: self.Cash > 100
TypeError: <lambda>() missing 1 required positional argument: 'self'
贪婪的杰克=人()
>>>贪婪的杰克·哈斯古德穆德=lambda self:self.Cash>100
TypeError:()缺少1个必需的位置参数:“self”
不幸的是,这不起作用。有没有其他方法可以改变方法
免责声明:以上示例仅用于演示。我知道我可以使用继承或保留现金阈值作为
人的财产。但这不是问题的重点。当你在一个类中编写一个def
,然后在一个实例上调用它时,这就是一个方法,当你调用它时,方法调用的机制将填充self
参数
通过在实例中指定给HasGoodMood
,您并没有在那里放置新方法,而是在属性中放置函数。您可以读取属性来获取函数并调用它,尽管这看起来像是一个方法调用,但它只是调用一个碰巧存储在属性中的函数。您不会自动获得self
参数
但是你已经知道了self将是什么,因为你要把这个函数赋给一个特定的对象
greedy_jack.HasGoodMood = (lambda self=greedy_jack: self.Cash > 100)
这将函数参数self
与变量贪婪_jack
的当前值相关联
Python中的lambda只能是一行。如果需要更长的函数,可以使用def
def greedy_jack_HasGoodMood(self=greedy_jack):
return self.Cash > 100
greedy_jack.HasGoodMood = greedy_jack_HasGoodMood
要了解一个不太老套的解决方案,请参阅。继承是一条可行之路
它可以简单到:
class Person(object):
Cash = 100
def HasGoodMood(self):
return self.Cash > 10
def SayHi(self):
if self.HasGoodMood():
print('Hello!')
else:
print('Hmpf.')
class newPersonObject(Person):
def HasGoodMood(self):
return self.Cash > 100
>>> greedy = newClassPerson()
>>> greedy.SayHi()
hmpf
当你这么做的时候,你在做同样的事情。您只覆盖了贪婪的jacks属性。用上面提到的方法,你可以创造贪婪的人,快乐的人,永远不快乐的人,嬉皮士等等
在我看来,更好的选择是在定义对象时接受cash参数。因此,您可以动态地使人们变得贪婪或正常。(未测试)
使用以下提示:
您可以通过使用“类型”模块为创建的对象指定一个方法而不影响类,从而执行以下操作。您需要这样做,因为函数不会自动接收self对象作为第一个变量,但方法会
import types
joe = Person()
bob = Person()
joe.SayHi()
>>> Hello!
def greedy_has_good_mood(self):
return self.Cash > 100
joe.HasGoodMood = types.MethodType(greedy_has_good_mood, joe)
joe.SayHi()
>>> Hmpf.
bob.SayHi()
>>> Hello!
@阿恩,dupe已经过时了,它只涉及Python 2。@DanielRoseman它在3中不再起作用了吗?@Arne那里有一些与Python 3相关的信息,但并不明显。事实上,很难说这些答案中的大多数是关于旧式类还是新式类。据我所知,Arne的dupe中的前三个答案确实适用于Python3。“我看那个被骗的目标没有什么问题。”阿兰·菲说得很对。Aaron的回答是用Python 3编写的。请参见免责声明:对于真实场景,这些都是正确且绝对可取的解决方案,但是,问题并不是特别要求它们。如果您介绍一些关于描述符和方法绑定的内容,来解释OP的实际问题,那将是一件好事。然而,虽然我不是你的创可贴解决方案的忠实粉丝,但我认为它不值得投票。
class Person(object):
def __init__(self, cash_to_be_happy):
self.cash = cash_to_be_happy
def HasGoodMood(self, has_money):
return has_money > self.cash
def SayHi(self, has_money):
if self.HasGoodMood(has_money):
print('Hello!')
else:
print('Hmpf.')
>>> joe = Person(100)
>>> joe.SayHi(150)
Hello!
>>> greedy_joe = Person(200)
>>> greedy_joe.SayHi(150)
Hmpf
import types
joe = Person()
bob = Person()
joe.SayHi()
>>> Hello!
def greedy_has_good_mood(self):
return self.Cash > 100
joe.HasGoodMood = types.MethodType(greedy_has_good_mood, joe)
joe.SayHi()
>>> Hmpf.
bob.SayHi()
>>> Hello!