7

我正在努力实现以下目标:

class A:
    username = None
    username = get_username()
    def get_username(self):
        if username is None:
            try:
                uname = os.environ["USER"]
            except:
                printf("Couldn't find a user name")
            return uname
        return username

不知道如何实现这一点。我确定我错过了一些“自我”。前缀,但这是我第一次使用 python 和静态成员。

从某种意义上说,我想要一个包含一些成员和函数的类来计算这些成员的值,但我不想重新计算。我也希望这些是静态函数和数据成员。

问题是函数“username = get_username()”行尚未定义。如果我将用户名放在函数之后,那么它不是

4

2 回答 2

13

首先,如果您只是要在之后立即重新分配它,则没有理由分配None给它。username

其次,如果你希望方法是静态方法,你不能给它一个self参数。如果你想要一个真正的静态方法,你必须明确声明它。

    @staticmethod
    def get_username():
        if username is None:
        ...

否则,您需要一个类 (that self) 的实例来调用它,而您还没有。

在 Python 3 中,任何常规方法在类上调用时都像静态方法一样,在实例上调用时就像实例方法一样。所以,如果你确定你永远不想调用a.get_username()实例a,你可以跳过装饰器。但是您仍然需要摆脱self参数。

我认为您实际上想要做的是使用类变量来记忆静态方法的结果。你不能这样做,但是你可以使用一个类变量来记忆一个方法的结果,这可能已经足够接近了。看起来像这样:

class A:
    username = None
    @classmethod
    def get_username(cls):
        if cls.username is None:
            try:
                uname = os.environ["USER"]
            except:
                print("Couldn't find a user name")
            else:
                cls.username = uname
        return cls.username

另一方面,没有充分的理由 username 必须是类成员。您可以通过向函数添加成员、传递可变默认变量或以不需要感染类的各种其他方式来记忆,并允许您get_username作为静态方法而不是类方法离开。

但实际上,最好的解决方案是在 PyPI、ActiveState 的配方列表等中找到一个记忆库,这样你就可以这样写:

class A:
    @memoize
    @staticmethod
    def get_username():
        try:
            return os.environ["USER"]
        except:
            print("Couldn't find a user name")
            return None

同样,@staticmethod如果您确定没有人会尝试创建A并调用get_username它的实例,则可以放弃。

于 2012-11-02T19:39:44.153 回答
1

如果您不想失去引用 A.username 的能力,可以使用带有一点元类的类属性:

class A(type):
    def __new__(cls, name, bases, attrs):
        # this allows B().username to also work
        attrs['username'] = property(lambda s: s.__class__.username)
        return type.__new__(cls, name, bases, attrs)
    @property
    def username(self):
        if not hasattr(self, '_username'):
            self._username = 'bar'
        return self._username

class B(object):
    __metaclass__ = A

print B.username
print B().username
于 2012-11-05T04:47:03.000 回答