Python中的封装
在这篇文章中,我们将看到OOPS概念封装在Python中的用法。
什么是封装
封装是将数据和将数据作为一个单元处理的代码(方法)保持在一起的过程。只能通过同一类中的方法来更改任何变量,该方法必须防止外部实体对数据进行任何有意或者无意的修改。
类是封装的一个示例,因为它包装了该类中定义的所有变量和方法。
用Python封装
由于类是封装的一个示例,因此在Python中定义一个包装所有变量和方法的类是实现封装的第一步。但是问题是如何停止外部访问变量,因为没有显式的访问修饰符,例如public,private,在Python中受保护,并且默认情况下所有变量都是public。这是一个例子来澄清它
class User: def __init__(self, name, age): self.name = name self.age = age def display_user(self): print('User Name:', self.name) print('User Age:', self.age) user = User('Mike Dallas', 34) # calling class method user.display_user() # Accessing variables directly print(user.name) print(user.age)
输出:
User Name: Mike Dallas User Age: 34 Mike Dallas 34
如我们所见,类的名称和年龄字段可以通过类方法访问,也可以直接在类外部访问。
如何在Python中控制访问
如通过示例所示,可以在Python类的外部直接访问字段,那么如何控制该访问以及如何在Python中进行适当的封装?
Python的概念是使用以单个下划线为前缀的变量(例如_name)和以双下划线为前缀的变量(例如__name)来给类中的访问控制提供一些相似之处。
使用单个下划线
用单个下划线给变量加上前缀只是Python代码中的约定,以表明意图是将此类类成员视为API的非公共部分(无论是函数,方法还是数据成员) 。对于其他开发人员而言,更多的指示是此类成员仅应在类范围内使用,而不应从类外部访问。
由于使用单个下划线只是一种约定,因此它实际上不会以任何方式更改变量的访问权限。
class User: def __init__(self, name, age): self.name = name self._age = age def display_user(self): print('User Name:', self.name) print('User Age:', self._age) user = User('Mike Dallas', 34) # calling class method user.display_user() # Accessing variables directly print(user.name) print(user._age)
输出:
User Name: Mike Dallas User Age: 34 Mike Dallas 34
我们可以看到age变量现在以单个下划线为前缀,但是仍然可以在类外部访问。通过"访问课程的受保护成员_age",我们会收到此警告。
使用双下划线
我们可以通过在其下加上双下划线前缀来最接近在Python中将类成员设为私有。此过程在Python中被称为名称处理,其中__var形式的任何标识符(至少两个前导下划线,至多一个下划线)在文本上被python解释器替换为_classname__var,其中classname是当前类名。
class User: def __init__(self, name, age): self.name = name self.__age = age def display_user(self): print('User Name:', self.name) print('User Age:', self.__age) user = User('Mike Dallas', 34) # calling class method user.display_user() # Accessing variables directly print(user.name) print(user.__age)
输出:
User Name: Mike Dallas User Age: 34 Mike Dallas Traceback (most recent call last): File "F:/theitroad/Programs/Example.py", line 16, in print(user.__age) AttributeError: 'User' object has no attribute '__age'
现在,年龄变量以双下划线为前缀,这会在内部将其名称更改为_User__age,因此无法从类外部访问它。从类中的方法仍然可以访问。
请注意,使用双下划线仅更改字段的名称,因此仍然可以通过使用更改后的名称来访问或者修改被视为私有的变量。
在示例中,我们可以将语句print(user .__ age)更改为print(user._User__age)以直接访问更改后的名称。