一、封装概念

  封装是面向对象的特征之一,是对象和类概念的主要特性。

  封装就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。

二、隐藏属性

  在python中用双下划线开头的方式将属性隐藏起来(设置成私有的)

  其实这仅仅这是一种变形操作,类中所有双下划线开头的名称如__x都会自动变形成:_类名__x的形式。

class A:
    __x = 1  # _A__x = 1

    def __init__(self, name):
        self.__name = name  # self._A__name='egon'

    def __foo(self):   # _A__foo
        print('%s foo run' % self.__name)

    def bar(self):
        self.__foo()  # self._A__foo()
        print('from bar')

# 无法找到类的属性和函数:
# print(A.__x)
# print(A.__foo)

print(A.__dict__)   # 可以查看到_A__foo;bar这两个函数
# 输出:{'__module__': '__main__', '_A__x': 1, '__init__': <function A.__init__ at 0x101f211e0>, '_A__foo': <function A.__foo at 0x101f21378>, 'bar': <function A.bar at 0x101f212f0>, '__dict__': <attribute '__dict__' of 'A' objects>, '__weakref__': <attribute '__weakref__' of 'A' objects>, '__doc__': None}

a = A('egon')
a._A__foo()  # 通过这种方式可以访问类隐藏函数
# 输出:egon foo run
a.bar()
"""
egon foo run
from bar
"""

  可以看到类的属性和函数在前面加'__',在类定义阶段就发生了变形,变形后在外部就无法通过.__x或.__func来调用。

1、自动变形的特点

  1)类中定义的__x只能在内部使用,如self.__x,引用的就是变形的结果。

  2)这种变形其实正是针对外部的变形,在外部是无法通过__x这个名字访问到的。

  3)在子类定义的__x不会覆盖在父类定义的__x,因为子类中变形成了:_子类名__x,而父类中变形成了:_父类名__x,即双下滑线开头的属性在继承给子类时,子类是无法覆盖的。

class Foo:
    def __func(self):   # _Foo_func
        print('from foo')


class Bar(Foo):
    def __func(self):   # _Bar__func
        print('from bar')
        
b = Bar()
# b.func()   # AttributeError:没有这个属性
b._Bar__func()  # 输出:from bar

2、变形需要注意的问题

  1)知道了类名和属性名就可以拼出名字:_类名__属性,然后就可以访问了

class B:
    __x = 1

    def __init__(self, name):
        self.__name = name

print(B._B__x)
"""
1
"""

  2)变形的过程只在类的定义时发生一次,定义后的赋值操作,不会变形

>>> class A:
...     def __init__(self):
...             self.__X=10
... 
>>> a=A()
>>> a.__dict__
{'_A__X': 10}
>>> a.__Y=2131
>>> a.__dict__
{'_A__X': 10, '__Y': 2131}    # __Y没有变形

  3)在继承中,父类如果不想让子类覆盖自己的方法,可以将方法定义为私有的

class A:
    def __foo(self):  # _A__foo
        print('A foo')

    def bar(self):
        print('A.bar')
        self.__foo()  # self._A__foo()

class B(A):
    def __foo(self):  # _B__foo
        print('B.foo')

b = B()
b.bar()
"""
A.bar
A foo  # 只在自己类找方法不去其他类查找,子类不覆盖父类方法
"""
#正常情况
>>> class A:
...     def fa(self):
...         print('from A')
...     def test(self):
...         self.fa()
... 
>>> class B(A):
...     def fa(self):
...         print('from B')
... 
>>> b=B()
>>> b.test()
from B


#把fa定义成私有的,即__fa
>>> class A:
...     def __fa(self): #在定义时就变形为_A__fa
...         print('from A')
...     def test(self):
...         self.__fa() #只会与自己所在的类为准,即调用_A__fa
... 
>>> class B(A):
...     def __fa(self):
...         print('from B')
... 
>>> b=B()
>>> b.test()
from A
方法私有的情况 

相关文章:

  • 2021-06-26
  • 2020-12-18
  • 2018-08-20
  • 2021-06-10
  • 2022-12-23
  • 2021-06-11
  • 2021-06-03
猜你喜欢
  • 2021-11-06
  • 2021-06-12
  • 2022-02-13
  • 2021-05-30
  • 2022-12-23
相关资源
相似解决方案