1

如果我有一个功能:

def foo(self, a, b):
    c = a + b
    return c

如何在不更改函数中的 c 的情况下调用 foo?所以假设我在另一个函数中调用 foo :

def bar(self):
    z = self.foo(2, 4)
    return (z)

然后我想在一个单独的函数中再次调用 foo ,但我想要从调用 'bar' 时开始的 c 。

def baz(self):
    self.foo(?, ?) # trying to just get c, without any changes.

基本上,我试图在课堂上保留一个帐户,以便其他班级可以访问同一个帐户;只是一个简单的平衡,加减钱。

谢谢。

4

6 回答 6

5

存储c为类变量或全局变量并覆盖函数以返回旧值。

例如

class SomeClass:
     def foo(self, a=None, b=None):
        if a and b:
            c = a + b
            self.stored_c = c
            return c
        return self.stored_c

注意:您必须处理何时更新stored_c和任何并发问题。

更新:WRT glglgl的评论,针对方法重载进行了更新。

于 2012-08-20T12:50:02.530 回答
3

c是函数本地的,而不是静态的。这意味着每次函数退出时,c都会收集垃圾。为什么不直接存储c第一次计算的值?这似乎是显而易见的答案。

于 2012-08-20T12:51:16.327 回答
3

我已经接受了 Rohan 提供的答案并提出了以下内容。它似乎有效,尽管可能有更好/首选的方法来实现这一点。

以下代码允许我跨多个类和方法跟踪帐户余额。

import os

class Foo():
    def __init__(self):
        self.stored_end = 0

    def account(self, a, b):
        c = float(a) + b
        print a
        print b
        print c
        self.stored_end = c
        print self.stored_end

    def testy(self, q, v):
        print "\n"
        print " _ " * 10
        z = float(q) + v
        print self.stored_end   
        self.stored_end = self.stored_end + z
        print " _ " * 10
        print self.stored_end

class Bar():
    def __init__(self):
        pass

    def zippy(self, a, b):
        print " _ " * 10
        print "this is zippy"
        foo.testy(a, b)

class Baz():
    def __init__(self):
        pass

    def cracky(self, g, m):
        y = g + m
        print " _ " * 10
        print "calling stored_end"
        foo.stored_end = foo.stored_end + y
        print " _ " * 10
        print "this is cracky"
        print "y = %r" % y
        print foo.stored_end    

os.system("clear")      
foo = Foo()
foo.account(5, 11)
foo.testy(100, 100)
bar = Bar()
bar.zippy(10, 100)
baz = Baz()
baz.cracky(1000, 1)
于 2012-08-20T17:36:48.797 回答
2

您需要有一些构造来保存最后的结果。例如,你可以对函数做一些包装

def keep_result(func):
    from functools import wraps
    @wraps(func)
    def wrapper(*a, **k):
        res = func(*a, **k)
        wrapper.last_result = res
        return res
    wrapper.func = func # makes it easy to bypass
    return wrapper

这就是所谓的“装饰器功能”。

现在如果你这样做

@keep_result
def foo(self, a, b)
    c = a + b
    return c

函数foo(它本身,而不是它的结果!)被用作一个参数,为keep_result()它创建一个wrapper()调用原始函数的新函数,将它的结果保存到一个属性中并返回结果。这个新函数将代替原来的函数返回foo()

所以你可以说

normal_result = foo(whatever)

然后做

saved_result = foo.last_result

你得到同样的结果。

于 2012-08-20T12:58:55.403 回答
1

为什么不将结果存储在 中self,并有可选参数来查看它是否应该用于任何计算?

就像是:

def foo(self, *args):
    if args:
        self.c = 0
        for value in args:
            self.c += value

    # In case `self.c` is not set yet, then use default of `0`
    return getattr(self, 'c', 0)

现在,如果您foo使用参数调用,它将添加所有参数并存储它。如果不带参数调用,它将返回最后存储的值。

于 2012-08-20T12:50:33.880 回答
1

看起来你想要的东西是一个缓存的属性。您可以制作一个装饰器实现描述符,将其作为将来使用的通用事物:

def cachedproperty(f):
    """Cached property.

    Calculated once - serves forever.
    """

    def get(self):
        try:
            return self._properties[f]
        except AttributeError:
            self._properties = {}
            self._properties[f] = f(self)
            x = self._properties[f]
            return x
        except KeyError:
            x = self._properties[f] = f(self)
            return x

    return property(get)

让我们看一下这个例子:

 class X(object):
     x = 0

     def __init__(self, x):
         self.x = x

     @cachedproperty
     def y(self):
         return self.x + 6

这里有一些测试。

 >>> ob = X(5)
 >>> ob.y
 11
 >>> ob.x = 10
 >>> ob.y
 11
于 2012-08-20T12:57:06.490 回答