3.1.6 封装

1. 封装其实就是在类定义的时候,对以__开头(不包括__xxx__是内置方法)的属性进行变形,并且只变形一次,只是类定义时。

2. 变形后,类外部无法直接使用obj_name.__attribute_name。但python无法做到真正的隐藏,外部依然可以使用变形后的属性进行调用。如:对象._类名__属性名

3. 类内部是可以直接调用__属性名。因为定义的时候都已经变形,内部使用时,直接使用变形后的属性。

4. 子类无法覆盖父类的__开头的属性。因为定义时就已经变形了。他们的类名不一样,变形后的属性也不一样。

# class A:
#     __x=1 #_A__x=1
#
#     def __init__(self,name):
#         self.__name=name #self._A__name=name
#
#     def __foo(self): #def _A__foo(self):
#         print('run foo')
#
#     def bar(self):
#         self.__foo() #self._A__foo()
#         print('from bar')

# print(A.__dict__)
# print(A.__x)
# print(A.__foo)

# a=A('egon')
# a._A__foo()
# a._A__x

# print(a.__name) #a.__dict__['__name']
# print(a.__dict__)

# a.bar()

'''
这种变形的特点:
    1、在类外部无法直接obj.__AttrName
    2、在类内部是可以直接使用:obj.__AttrName
    3、子类无法覆盖父类__开头的属性
'''


  

需要注意的问题:

1. 没有真正限制我们从外部调用,可以使用变形后的属性。

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

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

# 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()



# class B:
#     __x=1
#
#     def __init__(self,name):
#         self.__name=name #self._B__name=name

#验证问题一:

没有真正限制我们从外部调用,可以使用变形后的属性。
print(B._B__x)

#是可以调用的。 

#验证问题二:

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

B.__y=2
print(B.__dict__)   # __y 不会变形。
b=B('egon')
print(b.__dict__)

b.__age=18
print(b.__dict__)
print(b.__age)


#验证问题三:

在继承中,父类如果不想让子类覆盖自己的方法,可以将方法定义为__开头。


class A:
def foo(self):
print('A.foo')

def bar(self):
print('A.bar')
self.foo() #b.foo()

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


b=B()
b.bar()

输出:A.bar

     B.foo

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

    #因为子类B没有_A__foo(),所以输出的是父类自己的__foo(),故父类定义的__方法并不会被子类覆盖。

猜你喜欢

转载自www.cnblogs.com/beallaliu/p/9113827.html
今日推荐