Python程序设计案例课堂
上QQ阅读APP看书,第一时间看更新

6.9 类的封装

所谓类的封装(encapsulation),就是类将其属性(变量与方法)封装在该类内,只有该类中的成员可以使用该类中的其他成员。这种被封装的变量与方法,称为该类的私有变量(private variable)和私有方法(private method)。

Python类中的所有变量与方法都是公用的(public)。只要知道该类的名称与该变量或方法的名称,任何外部的对象都可以直接存取类中的属性与方法。

如下例所示,x是myClass类的实例变量,name是myClass类的变量。利用x.name就可以存取到myClass类中的name变量。

        >>> class myClass:
              def __init__(self):
                self.name = None

        >>> x = myClass()
        >>> x.name = "Andy"
        >>> a = x.name
        >>> print (a)
        Andy

1.封装Python类的原则

要做到类的封装,Python提供以下两个原则。

(1)属性(变量与方法)名称的第一个字符如果是单底线,则此属性视为类的内部变量,外面的变量不可以引用此属性。

(2)属性(变量与方法)名称的前两个字符如果都是单底线,则编译时属性名称attributeName会被改成_className_attributeName, className是该类的名称。由于属性名称之前加上了类的名称,所以与类中原有的属性名称有差异。

这两个原则只是提供作为参考,Python类中的所有属性仍然都是公用(public)的。只要知道类与属性的名称,仍然可以存取类中的所有属性。例如:

        >>>class myClass:
          def __init__(self, value):
              self._n = value       #第一个字符是单底线的变量_n
        self.__n = value            #前两个字符都是单底线的变量__n
        def __func(self):           #前两个字符都是单底线的函数__func()
        print (self._n + 1)

        >>>x = myClass(100)
        >>>x._n                     #第一个字符是单底线的变量_n,可以任意存取
        100
        >>>x.__n                    #错误,因为__n已经被改名为_myClass__n
        Traceback (most recent call last):
          File "<pyshell#376>", line 1, in <module>
            x.__n
        AttributeError: 'myClass' object has no attribute '__n'
        >>> x._myClass__n           #正确
        100
        >>> x.__func()              #错误,因为__func()已经被改名为_myClass__func()
        Traceback (most recent call last):
          File "<pyshell#378>", line 1, in <module>
            x.__func()
        AttributeError: 'myClass' object has no attribute '__func'
        >>>x._myClass__func()       #正确
        101

2.类命名空间

类中的所有属性都存储在该类的命名空间(namespace)内。因此,如果在类中存储了一个全局变量的值,此值就会被放置在该类的命名空间内。就算以后此全局变量的值被改变了,类内的该值仍然维持不变。

下列案例设置一个全局变量w = 10,在myClass类中使用storeVar()函数存储此值。当全局变量w的值改变时,myClass类中的值仍然维持不变。

        >>> class myClass:
              w = 10
            def storeVar(self, n = w):
                        return n

        >>> x = myClass()
        >>> x.storeVar()
        10
        >>> w = 20
        >>> x.storeVar()
        10