将 class 属性别名为函数

Aliasing a class attribute to a function

是否可以做类似下面的事情:

class foo():
    def bar():  # a method that doesn't take any args
        # slow calculation
        return somefloat

    b = bar  # bar is a function but b just gives you the float attribute

f = foo()
f.b  # returns somefloat but doesn't require the empty parentheses

我希望这个例子很清楚,因为我不太清楚我想做的事情的术语是什么。我的基本目标是为没有参数的方法删除一堆括号,以使代码更清晰易读。

该函数速度慢且很少使用,因此实时计算比提前计算一次并存储变量更容易。

这可能吗?这是好的做法吗?有没有更好的方法?

b = bar 显然不行。但是 属性 最简单的 "doesn't require the empty parentheses" 问你:

b = property(bar)

现在每次访问 f.b 都会调用 f.bar() "behind the curtains"。

然而,这意味着如果您访问 f.b 两次,f.bar() 将被调用两次,重复计算。如果重复是无关紧要的(即,如果对同一个对象的重复计算结果没有改变)你可以做得更好("caching" 的结果在 f.b 中永远一旦它第一次被计算) - 一些喜欢:

class foo(object):
    def bar(self):  # a method that doesn't take any args
        # slow calculation
        return somefloat

    def _cache_bar(self):
        result = self.bar()
        setattr(self, 'b', result)
        return result

    b = property(_cache_bar)

实现这个的标准方法是使用property, which is a decorator:

class Foo():

    @property
    def bar(self):
        # slow calculation
        return somefloat


f = Foo()

f.bar  # returns somefloat but doesn't require the empty parentheses

有两点需要注意:

  1. 您仍然需要像往常一样在方法签名中使用 self,因为有时您需要引用例如self.some_attribute 方法内部。如您所见,这根本不会影响 属性 的 use

  2. 没有必要用 f.bar() 方法和 f.b 属性 让你的 API 变得混乱 - 最好决定什么最有效对你的 class 有意义,而不是提供一堆不同的方法来做同样的事情。

通过静态方法,但需要通过括号调用。

class foo(object):
    @staticmethod
    def bar():  # a method that doesn't take any args
        # slow calculation
        return "abc"

    b = bar  # bar is a function but b just gives you the float attribute

f = foo()
print f.b()

输出:

$ python test.py 
abc