在Python中使用类变量作为非默认参数

8

有没有一种方法可以在类内保留私有类变量,并将其用作非默认变量的默认值(在类外不定义该值的情况下)?

示例:

class a:
    def __init__(self):
        self.__variable = 6
    def b(self, value = self.__variable):
        print value

5
Python没有私有类变量,完全没有。你使用的双下划线并不能使变量变为私有,它只是进行名称混淆以避免名称冲突。除非你知道必须使用双下划线,否则不要使用它。;) - Lennart Regebro
很棒的问题!(解决了我遇到的一个巨大问题,所以...) - nchpmn
3个回答

14

你在过度思考这个问题:

class a:

    def __init__(self):
        self.__variable = 6

    def b(self, value=None):
        if value is None:
            value = self.__variable
        print value

4
  1. self.__variable是实例变量,而不是类变量。
  2. 因为默认参数在函数方法定义时被计算,所以你不能直接使用实例变量作为默认参数(通常的技巧是将默认值设为None并在函数体中添加if arg is None: arg = real_default,这样可以解决问题)。
  3. 前导双下划线不表示“私有”,它们表示“名称混淆和麻烦”。如果你不知道我指的具体是什么,那么你根本不应该使用这个“特性”。它的预期用途不是私有成员 - 用一个下划线就足够了。

那么,预期的使用是什么? - Karl Knechtel
1
@Karl:在子类中避免名称冲突。请参见例如http://docs.python.org/reference/lexical_analysis.html#reserved-classes-of-identifiers或http://docs.python.org/tutorial/classes.html?highlight=mangling#private-variables(第三段)。 - user395760
如果我只使用一个下划线,仍然可以访问变量。 - calccrypto
4
当然可以,为什么不行呢?实际上相反的是:由于名称重整,你不能在类定义之外合理地访问__variable。这就是为什么我强烈建议你删除一个下划线。 - user395760
3
@calccrypto 是的,没问题。Python 的假设是我们都是成年人,理解未经明确许可(来自该类文档)就访问另一个类变量是不好的行为。(即使有许可,现在我们也有 property 包装器。)如果我想要那种编译时检查的级别,我就不会使用动态类型语言。 - Karl Knechtel

4
值得补充的是,如果您想让 None 成为可接受参数的范围之内,您可以创建一个自定义的标识值,在代码中不被用于其他任何目的。否则,b 永远不会返回 valueNone
UseDefault = object()

# Python 3? Otherwise, you should inherit from object unless you explicitly
# know otherwise.
class a:    
    def __init__(self):
        self._variable = 6

    def b(self, value=UseDefault):
        if value is UseDefault:
            value = self._variable
        print value

现在如果不传递参数给b,就会使用默认值。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接