【目录】@2020.4.8

一、引入

二、隐藏属性

1、如何隐藏属性

2、需要注意的几点问题

三、开放接口

1、隐藏数据接口

2、隐藏函数接口

四、装饰器property

 

面向对象编程有三大特性:封装、继承、多态,其中最重要的一个特性就是封装

封装指的就是把数据与功能都整合到一起,之前所说的”整合“二字其实就是封装的通俗说法。

除此之外,针对封装到对象或者类中的属性,我们还可以严格控制对它们的访问,分两步实现:隐藏与开放接口

 

二、隐藏属性

 1、为何要隐藏属性

  • 隐藏数据属性,将数据隐藏起来就限制了类外部对数据的直接操作。

  • 隐藏函数属性,目的是隔离程序的复杂度 。

2、如何隐藏属性?

python的class机制采用双下划线开头的方式将属性隐藏起来(设置成私有的)。

但其实这仅仅只是一种变形操作,类中所有双下滑线开头的属性,

都会在类定义阶段、检测语法时自动变成“ _类名__属性名 ”的形式:

## 定义类
class
Foo:

#  隐藏数据属性
__N=0 # ——变形为 _Foo__N def __init__(self): # 定义函数时,会检测函数语法,所以__开头的属性也会变形 self.__x=10 # 变形为 self._Foo__x
#  隐藏函数属性 def __f1(self): # 变形为 _Foo__f1 print('__f1 run') def f2(self): # 定义函数时,会检测函数语法,所以__开头的属性也会变形 self.__f1() #变形为self._Foo__f1()
##  实例化类 print(Foo.__N) # 报错AttributeError:类Foo没有属性__N obj = Foo() print(obbj.__x) # 报错AttributeError:对象obj没有属性__x

 

3、需要注意的几点问题

(1)在类外部无法直接访问双下滑线开头的属性,但知道了类名和属性名就可以拼出名字: _类名__属性,然后就可以访问了,如foo._a__n所以说这种操作并没有严格意义上地限制外部访问,仅仅只是一种语法意义上的变形。

class Foo:
    __x = 1  # _Foo__x

    def __f1(self):  # _Foo__f1
        print('from test')

print(Foo.__dict__)  # 查看类Foo的属性
print(Foo._Foo__x)   # 访问隐藏的数据属性 __x
print(Foo._Foo__f1)  #访问隐藏的函数属性 __f1


(2) 这种隐藏对外不对内,即在类内部是可以直接访问双下滑线开头的属性的,比如self.__f1(),

因为在类定义阶段,类内部双下滑线开头的属性统一发生了变形。

class Foo:
    __x = 1  # _Foo__x = 1

    def __f1(self):  # _Foo__f1
        print('from test')

    def f2(self):
        print(self.__x)  # print(self._Foo__x)
        print(self.__f1)   # print(self._Foo__f1) ,得到 _Foo__f1 的内存地址
        print(self.__f1())   # print(self._Foo__f1()),打印函数 _Foo__f1的返回结果,先是打印输出 from test,再打印返回值,若未赋值,默认为None

# print(Foo.__x)  #  AttributeError: type object 'Foo' has no attribute '__x'
# print(Foo.__f1)  #  AttributeError: type object 'Foo' has no attribute '__f1'
obj=Foo()
obj.f2()

# 输出结果:
1

<bound method Foo.__f1 of <__main__.Foo object at 0x000001B109AF9760>>

from test
None    

#为何返回一个 None 值?
print(self.__f1())   # print(self._Foo__f1()),打印函数 _Foo__f1的返回结果,先是打印输出 from test,再打印返回值,若未赋值,默认为None

 #为何返回一个 None 值?

 1 class Foo:
 2     __x = 1  # _Foo__x = 1
 3 
 4     def __f1(self):  # _Foo__f1
 5         print('from test')
 6         return 2  #  若没有设返回值,则默认返回 None
 7         # return 'hello world'  #也可返回字符串,可以返回任意格式正确的值
 8         # return {1,2,3,4}
 9 
10 
11     def f2(self):
12         print(self.__x)  # print(self._Foo__x)
13         print(self.__f1)  # print(self._Foo__f1)
14         print(self.__f1())
15 
16 # print(Foo.__x)  #  AttributeError: type object 'Foo' has no attribute '__x'
17 # print(Foo.__f1)  #  AttributeError: type object 'Foo' has no attribute '__f1'
18 obj=Foo()
19 obj.f2()
20 
21 
22 # 输出结果:
23 # 1
24 # <bound method Foo.__f1 of <__main__.Foo object at 0x000001801DAB9760>>
25 # from test
26 # 2
27 
28 
29 # ------将 f1改为正常的函数,不隐藏,直接执行
30 
31 class Foo:
32     __x = 1  # _Foo__x = 1
33 
34     def f1(self):  # _Foo__f1
35         print('from test')
36 
37 obj=Foo()
38 obj.f1()  # 直接执行 f1()
39 
40 # 输出结果:
41 from test
42 
43 
44 # -------不管f1隐藏与否, print(self.f1())  # print(self._Foo__f1()) ,都是在打印 f1方法的返回结果,一定要有个返回值,即return 返回值
45 
46 class Foo:
47     __x = 1  # _Foo__x = 1
48 
49     def f1(self):  # _Foo__f1
50         print('from test')
51         return 1   #  若没有设返回值,则默认返回 None
52 
53     def f2(self):
54         print(self.__x)  # print(self._Foo__x)
55         print(self.f1)   # print(self._Foo__f1)
56         print(self.f1())  # print(self._Foo__f1())  打印 f1方法的返回结果,先是执行 print('from test'),再打印返回值,若没有设返回值,则默认返回 None
57 
58 obj=Foo()
59 obj.f2()
60 
61 # 输出结果:
62 1
63 <bound method Foo.f1 of <__main__.Foo object at 0x000001CA79079760>>
64 from test
65 1
折腾了一下子---View Code

相关文章: