如何在Python类

时间:2016-01-23 01:13:55

标签: python

我已经搜索了一堆,似乎无法弄清楚如何实际执行此操作:

鉴于我有一个通用的实用方法,如下:

def __square(n):
    return n*n

然后我有一些类我可能想在内部使用这个方法:

def __square(n):
    return n*n

class Foo:
    def __init__(self):
        self.baz = 2

    def bar(self):
        return self.baz + __square(self.baz)

嗯,这不起作用。我得到NameError '_Foo__square' is not defined

为什么?

作为一种解决方法,我最终做了这样的事情:

class Foo:
    def __init__(self):
        self.baz = 2

    def bar(self):
        return baz + self.square(self.baz)

    def square(self,n):
        return n*n

但这对我来说很愚蠢,因为square函数与Foo实例无关,我也不希望或希望它成为Foo实例上的方法。

" pythonic"" pythonic"处理这类事情的方式?

修改

我想出了至少一部分内容:我得到了这种行为,因为我认为这些实用程序方法是私有的,我将它们命名为def __square(n):

我没有意识到这很特别,在输入上面的示例时,我最初并没有这样输入。我现在编辑了这个问题,以反映它实际输入的方式。

所以现在我的问题是:为什么将__置于顶级方法之前打破它,或者似乎?我明白这是命名和私人事物的约定。在Python中,因为它在这种情况下不起作用,你会推荐什么呢?

1 个答案:

答案 0 :(得分:7)

您不应该在函数名前加上两个下划线 - __ - 只要在类中的代码中找到以两个下划线名称为前缀的名称,Python编译器就会执行名称重整操作。 - 因此,在编译(到字节码)时,对__square的引用转换为对不存在的_Foo_square的引用。

只需在_中使用一个_square,就不会出现此错误。

Python没有像“私人”这样的名字。按照惯例 - 仅限于约定 - 不应该从其他范围的代码中调用或访问前缀为_的函数或属性。

有些人在互联网上写了一些文章,试图为其他广为人知的OOP语言中存在的每个概念创建等价,实际上提到双下划线前缀相当于这些语言中的“私有”变量。这是旧文档中的一个常见错误 - 最近的文章避免了这个错误。

双下划线前缀的行为有所不同 - 有时可以与private(与protected)属性相同的目的:它确实在操作中转换变量名称在Python的文档中称为“名称修改”。通常这用于属性名称,并且它被转换为容器类唯一的名称,默认情况下,它只能在定义的类上访问,而不能在其子类上访问。转换是确定性的并且有详细记录:一个下划线和类名称前置于属性的名称(包括两个下划线)。因此,具有Polygon属性的__area类在运行时实际上会有_Polygon__area - 如果派生的class Square(Polygon):类将尝试访问{{1}在其代码中,它实际上会在运行时访问__area。 (但是可以通过在代码中明确地编写_Square__area来读取和编写超类“__area