Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
我可以替换Python中对象的现有方法吗?_Python_Python 3.x_Methods - Fatal编程技术网

我可以替换Python中对象的现有方法吗?

我可以替换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

Q:在Python(3.6)中有没有办法改变现有对象的方法?(所谓“方法”是指作为参数传递的函数。)


示例

假设我有一个类
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!