首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从类外部访问自我

从类外部访问自我
EN

Stack Overflow用户
提问于 2012-04-15 20:27:41
回答 2查看 1.8K关注 0票数 4

我试图在类中的某些方法上实现一个修饰器,以便如果尚未计算该值,则该方法将计算该值,否则它将只返回预计算值,该值存储在实例defaultdict中。我似乎不知道如何从类之外声明的装饰器内部访问实例defaultdict。对于如何实现这一点,有什么想法吗?

下面是导入(对于一个工作示例):

代码语言:javascript
复制
from collections import defaultdict
from math import sqrt

这是我的装饰师:

代码语言:javascript
复制
class CalcOrPass:
    def __init__(self, func):
        self.f = func

    #if the value is already in the instance dict from SimpleData,        
    #don't recalculate the values, instead return the value from the dict
    def __call__(self, *args, **kwargs):

        # can't figure out how to access/pass dict_from_SimpleData to here :(
        res = dict_from_SimpleData[self.f.__name__]
        if not res:
            res = self.f(*args, **kwargs)
            dict_from_SimpleData[self.f__name__] = res
        return res

下面是带有修饰方法的SimpleData类:

代码语言:javascript
复制
class SimpleData:
    def __init__(self, data):
        self.data = data
        self.stats = defaultdict() #here's the dict I'm trying to access

    @CalcOrPass
    def mean(self):
        return sum(self.data)/float(len(self.data))

    @CalcOrPass
    def se(self):
        return [i - self.mean() for i in self.data]

    @CalcOrPass
    def variance(self):
        return sum(i**2 for i in self.se()) / float(len(self.data) - 1)

    @CalcOrPass
    def stdev(self):
        return sqrt(self.variance())

到目前为止,我已经尝试在SimpleData中声明装饰师,试图与装饰者传递多个论点(显然你不能这么做),并且在我的转椅上旋转,同时试图把纸飞机扔进我的蝎子油箱。任何帮助都将不胜感激!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-04-15 21:04:12

定义装饰器的方式--目标对象信息丢失。使用函数包装器,而不是:

代码语言:javascript
复制
def CalcOrPass(func):
    @wraps(func)
    def result(self, *args, **kwargs):
        res = self.stats[func.__name__]
        if not res:
            res = func(self, *args, **kwargs)
            self.stats[func.__name__] = res
        return res
    return result

wraps来自functools,这里没有严格的必要,但非常方便。

附带注意:defaultdict接受一个工厂函数参数:

代码语言:javascript
复制
defaultdict(lambda: None)

但是,由于您正在测试密钥的存在性,所以您应该更喜欢一个简单的dict

票数 4
EN

Stack Overflow用户

发布于 2012-04-15 21:23:54

在定义函数时,您不能做您想做的事情,因为它是未绑定的。下面是一种在运行时以通用方式实现该功能的方法:

代码语言:javascript
复制
class CalcOrPass(object):
    def __init__(self, func):
        self.f = func

    def __get__(self, obj, type=None): # Cheat.
        return self.__class__(self.f.__get__(obj, type))

    #if the value is already in the instance dict from SimpleData,
    #don't recalculate the values, instead return the value from the dict
    def __call__(self, *args, **kwargs):
        # I'll concede that this doesn't look very pretty.
        # TODO handle KeyError here
        res = self.f.__self__.stats[self.f.__name__]
        if not res:
            res = self.f(*args, **kwargs)
            self.f.__self__.stats[self.f__name__] = res
        return res

简短的解释:

  • ,我们的装饰器定义了__get__ (因此被称为描述符)。虽然属性访问的默认行为是从对象的字典中获取属性,但如果定义了描述符方法,Python将调用它。parameters.
  • Then
  • 对象的情况是,object.__getattribute__将像b.x这样的访问转换为function.
  • Note,我们可以从描述符的parameters.
  • Then访问绑定类及其类型,我们创建了一个新的CalcOrPass对象,它现在装饰了一个绑定方法,而不是旧的未绑定function.
  • Note--新的样式类定义。我不确定这是否适用于旧风格的类,因为我还没有试过;只是不要使用这些。)这将同时适用于函数和方法,however.
  • What恰好发生在“旧”修饰函数上,这是一个练习。
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10165768

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档