如何正确使用Python中的私有函数?

How do you correctly use private functions in Python?

本问题已经有最佳答案,请猛点这里访问。

我对Python不熟悉,在涉及私有函数时,我面临一些问题。我想在一个公共方法中调用其中的两个,只是为了让代码看起来更清晰,但是我根本无法理解运行时错误显示的内容。以下是完整代码中有问题的部分:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
def __loadVec(self,vec,res):
    for i in range(0,res.getRows()):
        for j in range(0,res.getColumns()):
            vec.append(self.matrix[i][j])
    return

def __savetoMatrix(self,vec,res):
    index = 0
    for i in range(0,res.getRows()):
        for j in range(0,res.getColumns()):
            self.matrix[i][j] = vec[index]
            index += 1
    return

def fmatrixSort(self,res):
    try:
        print"Sorting matrix information..."
        vec = []
        self._matrix.__loadVec(vec,res)
        vec.sort()
        self_matrix.__savetoMatrix(vec,res)
    except TypeError:
        print"TypeError in fmatrixSort"            
    return

我要做的是完全组织一个矩阵,这样它从最低的值开始,以最高的值结束。

这是程序显示的错误:

1
2
3
4
5
6
7
8
Traceback (most recent call last):
  File"MatrixClass.py", line 211, in <module>
    main()
  File"MatrixClass.py", line 203, in main
    mat.fmatrixSort(res)
  File"MatrixClass.py", line 154, in fmatrixSort
    self._matrix.__loadVec(vec,res)
AttributeError: matrix instance has no attribute '_matrix'

我该怎么解决这个问题?


python不完全具备private函数的概念。但是,它确实处理了类属性,这些属性的名称至少以两个底线开始,并且以最多一个底线结束,这有点特别——它会对名称进行管理,使其稍微难以访问。在本例中,您可以看到函数__func2的名称已损坏。仍然可以访问和调用该函数,但您必须特别努力才能做到这一点,只需调用o.func2()就失败了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
james@bodacious:tmp$cat test.py

class myclass:

    def func1(self):
        print"one"

    def __func2(self):
        print"two"

o = myclass()

print dir(o)

o._myclass__func2()
o.func2()
james@bodacious:tmp$python test.py
['__doc__', '__module__', '_myclass__func2', 'func1']
two
Traceback (most recent call last):
  File"test.py", line 15, in <module>
    o.func2()
AttributeError: myclass instance has no attribute 'func2'
james@bodacious:tmp$

所以要回答你的问题:

How do you correctly use private functions in Python?

答案是:就像其他任何函数一样,但是您必须知道被损坏的名称。

继续问你想问的问题:

1
AttributeError: matrix instance has no attribute '_matrix'

这是来自第154行:

1
self._matrix.__loadVec(vec,res)

错误消息告诉您,名为self的对象是类matrix的实例;但它没有名为_matrix的属性。提到上面的__savetoMatrix函数,它看起来像是简单地称为matrix—所以您需要将它称为self.matrix(称为self对象的matrix属性)。

这是__savetoMatrix函数引用self.matrix而不是self._matrix

然而,这里有一个更深的问题。在两行之间读取时,似乎该代码来自一个名为matrix的类;该类的实例具有一个名为matrix的属性。调用self.matrix.__loadVec()时,调用的是名为__loadvec()的函数,该函数绑定到绑定到名为self的对象的属性matrix上。

即使这是您想要做的,也不会起作用,因为上面所述的名称混乱——假设名为matrix的属性具有类inner_matrix,则必须将该函数称为self._matrix._inner_matrix__loadVec()

我认为您实际要做的是调用在类matrix中定义的名为__loadvec()的方法。要做到这一点,你只需要打电话给self.__loadVec()。因为它是对同一类中某个函数的调用,所以您甚至不需要担心名称的混乱——这些函数是在类中使用的,解释器将为您处理混乱。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
james@bodacious:tmp$cat test.py

class myclass:

    def func1(self):
        print"one"

    def __func2(self):
        print"two"

    def func3(self):
        self.__func2()
        print"three"

o = myclass()
print dir(o)
o.func3()
james@bodacious:tmp$python test.py
['__doc__', '__module__', '_myclass__func2', 'func1', 'func3']
two
three


在代码的几个部分中混合了self.matrixself._matrixself_matrix。最有可能的是,你指的是self.matrixself._matrix,其他的都是拼写错误。另外,fmatrixSort可能会在self上调用__loadVec__savetoMatrix,而不是当前所做的。

附加说明:

如果没有要返回的值,则不需要在函数结束时执行return。当执行到达函数的末尾时,函数将自动返回。

可以通过3种方式调用range

1
2
3
range(stop)
range(start, stop)
range(start, stop, step)

如果要从0开始范围,只需去掉start参数并用1个参数调用range