gpt4 book ai didi

python - 在函数属性中访问 self

转载 作者:太空狗 更新时间:2023-10-29 22:18:14 34 4
gpt4 key购买 nike

我正在尝试添加一个装饰器,该装饰器将可调用属性添加到函数,这些函数返回的对象与函数的返回值略有不同,但会在某个时候执行该函数。

我遇到的问题是,当函数对象被传递到装饰器时,它是未绑定(bind)的并且不包含隐式的 self 参数。当我调用创建的属性函数(即 string())时,我无法访问 self,也无法将其传递给原始函数。

def deco(func):
"""
Add an attribute to the function takes the same arguments as the
function but modifies the output.
"""
def string(*args, **kwargs):
return str(func(*args, **kwargs))
func.string = string
return func


class Test(object):

def __init__(self, value):
self._value = 1

@deco
def plus(self, n):
return self._value + n

当我去执行装饰器创建的属性时,这是我得到的错误,因为 args 不包含 self 引用。

>>> t = Test(100)
>>> t.plus(1) # Gets passed self implicitly
101
>>> t.plus.string(1) # Does not get passed self implicitly
...
TypeError: plus() takes exactly 2 arguments (1 given)

有没有一种方法可以创建这样的装饰器,它可以获得对self 的引用?或者有没有办法绑定(bind)添加的属性函数 (string()) 以便它被隐式 self 调用 参数?

最佳答案

您可以使用 descriptors这里:

class deco(object):

def __init__(self, func):
self.func = func
self.parent_obj = None

def __get__(self, obj, type=None):
self.parent_obj = obj
return self

def __call__(self, *args, **kwargs):
return self.func(self.parent_obj, *args, **kwargs)

def string(self, *args, **kwargs):
return str(self(*args, **kwargs))


class Test(object):

def __init__(self, value):
self._value = value

@deco
def plus(self, n):
return self._value + n

这样:

>>> test = Test(3)
>>> test.plus(1)
4
>>> test.plus.string(1)
'4'

这需要一个解释。 deco 是一个装饰器,但它也是一个 descriptor .描述符是一个对象,它定义了在将该对象作为其父对象的属性进行查找时调用的替代行为。有趣的是,边界方法本身是使用描述符协议(protocol)实现的

那是一口。让我们看看运行示例代码时会发生什么。首先,当我们定义 plus 方法时,我们应用了 deco 装饰器。现在通常我们把函数看作装饰器,函数的返回值就是装饰后的结果。这里我们使用类作为装饰器。因此,Test.plus 不是函数,而是 deco 类型的实例。该实例包含对我们希望包装的 plus 函数的引用。

deco 类有一个__call__ 方法,允许它的实例像函数一样工作。此实现只是将给定的参数传递给它引用的 plus 函数。请注意,第一个参数将是对 Test 实例的引用。

棘手的部分在于实现 test.plus.string(1)。为此,我们需要引用 test 实例,其中 plus 实例是一个属性。为此,我们使用描述符协议(protocol)。也就是说,我们定义了一个 __get__ 方法,只要 deco 实例作为某个父类实例的属性被访问,该方法就会被调用。发生这种情况时,它将父对象存储在自身内部。然后我们可以简单地将 plus.string 实现为 deco 类的方法,并使用对存储在 deco 实例中的父对象的引用获取 plus 所属的 test 实例。

这有很多魔法,所以这里有一个免责声明:虽然这看起来很酷,但实现这样的东西可能不是一个好主意。

关于python - 在函数属性中访问 self,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40185890/

34 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com