Python封装及实现方法

Python封装及实现方法

什么是封装?

在设计类时,刻意地将一些属性和方法隐藏在类的内部,这样在使用此类时,将无法直接以“类对象.属性名”(或者“类对象.方法名(参数)”)的形式调用这些属性(或方法),而只能用未隐藏的类方法间接操作这些隐藏的属性和方法。封装绝不是将类中所有的方法都隐藏起来,一定要留一些像键盘、鼠标这样可供外界使用的类方法。

封装的好处是什么?

封装机制保证了类内部数据结构的完整性,因为使用类的用户无法直接看到类中的数据结构,只能使用类允许公开的数据,很好地避免了外部对内部数据的影响,提高了程序的可维护性。

一个类实现良好的封装,用户只能借助暴露出来的类方法来访问数据,我们只需要在这些暴露的方法中加入适当的控制逻辑,即可轻松实现用户对类中属性或方法的不合理操作。

对类进行良好的封装,还可以提高代码的复用性。

Python 类如何封装?

Python 类中的变量和函数,不是公有的(类似 public 属性),就是私有的(类似 private),这 2 种属性的区别如下:

1. public:公有属性的类变量和类函数,在类的外部、类内部以及子类中,都可以正常访问;

2. private:私有属性的类变量和类函数,只能在本类内部使用,类的外部以及子类都无法使用。

默认情况下,Python 类中的变量和方法都是公有(public)的,它们的名称前都没有下划线 “_”,如果类中的变量和函数,其名称以双下划线“__”开头,则该变量(函数)为私有变量(私有函数),其属性等同于 private。

除此之外,还可以定义以单下划线“_”开头的类属性或者类方法(例如 _name、_display(self)),这种类属性和类方法通常被视为私有属性和私有方法,虽然它们也能通过类对象正常访问,但这是一种约定俗称的用法,初学者一定要遵守。

例如,如下程序示范了 Python 的封装机制:

class Students:

def set_name(self, name):

if len(name) < 3:

raise ValueError('名称长度必须大于3!')

self.__name = name

def get_name(self):

return self.__name

name = property(get_name, set_name) # 为 name 配置 setter 和 getter 方法

def set_add(self, add):

if add.startswith("http://"):

self.__add = add

else:

raise ValueError('地址必须以 http:// 开头')

def get_add(self):

return self.__add

add = property(get_add, set_add) # 为 add 配置 setter 和 getter 方法

# 定义个私有方法

def __display(self):

print(self.__name, self.__add)

student = Students()

student.name = "大切切"

student.add = "http://www.cnblogs.com/bigcarcar"

print(student.name)

print(student.add)

###运行结果

大切切

http://www.cnblogs.com/bigcarcar

上面程序中,Students 将 name 和 add 属性都隐藏了起来,但同时也提供了可操作它们的“窗口”,也就是各自的 setter 和 getter 方法,这些方法都是公有(public)的。

通过此程序的运行逻辑不难看出,通过对 Students 类进行良好的封装,使得用户仅能通过暴露的 setter() 和 getter() 方法操作 name 和 add 属性,而通过对 setname() 和 setadd() 方法进行适当的设计,可以避免用户对类中属性的不合理操作,从而提高了类的可维护性和安全性。

其中__display()为该类私有(private)方法,且该类没有提供操作该私有方法的“窗口”,因此我们无法在类的外部使用它。如下调用 __display() 方法是不可行的

student.__display() # 发起调用

### 返回报错

Traceback (most recent call last):

File "tests.py", line 68, in

student.__display()

AttributeError: 'Students' object has no attribute '__display'

封装原理详解

事实上,Python 封装特性的实现纯属“投机取巧”,之所以类对象无法直接调用以双下划线开头命名的类属性和类方法,是因为其底层实现时,Python 偷偷改变了它们的名称。

事实上,对于以双下划线开头命名的类属性或类方法,Python 在底层实现时,将它们的名称都偷偷改成了 "_类名__属性(方法)名" 的格式。

### 用下列方式可以访问到类中的私有属性

student._Students__display()

print(student._Students__name)

print(student._Students__add)

### 运行结果:

大切切 http://www.cnblogs.com/bigcarcar

大切切

http://www.cnblogs.com/bigcarcar

甚至于,我们还可以通过这种方式修改 student 对象的私有属性,例如:

### 修改对象私有属性

student._Students__name = '麻花藤'

student._Students__add = 'www.qq.com'

print(student._Students__name)

print(student._Students__add)

### 运行结果:

麻花藤

www.qq.com

总结

Python 类中所有的属性和方法,都是公有(public)属性,如果希望 Python 底层修改类属性或者类方法的名称,以此将它们隐藏起来,只需将它们的名称前添加双下划线(“__”)即可。