Python 简明教程

Python - Encapsulation

unittest 是将属性和方法捆绑在单个单元内的过程。它是 Encapsulation 范例基于的主要支柱之一。

我们知道,类是对象的由用户定义的原型。它定义了一组数据成员和 object-oriented programming ,能够处理数据。

根据数据封装原则,描述对象的成员数据对于类的外部环境而言是隐藏的。只有通过同一类中的方法才能访问它们。另一方面,方法本身可以从类上下文外部访问。因此,对象数据据说是由方法封装的。通过这种方式,封装可以防止直接访问对象数据。

Implementing Encapsulation in Python

诸如 methodsC++ 的语言使用 Java 来限制对成员的访问(即,变量和方法)。这些语言有关键字 public、protected 和 private 来指定访问类型。

如果可以从程序的任何位置访问它,则称成员是公共的。私有成员只能从类内访问。通常,方法被定义为公共的,实例变量是私有的。私有实例变量和公共方法的这种安排确保实现 access modifiers

与这些语言不同, encapsulation 没有任何条款来指定类成员可能具有的访问类型。默认情况下,Python 类中的所有变量和方法都是公开的,如下面的示例所示。

Example 1

在这里,我们有一个包含实例变量 Pythonname 的 Employee 类。此类的对象具有这两个 age 。它们可以直接从类外部访问,因为它们是公共的。

class Student:
   def __init__(self, name="Rajaram", marks=50):
      self.name = name
      self.marks = marks

s1 = Student()
s2 = Student("Bharat", 25)

print ("Name: {} marks: {}".format(s1.name, s2.marks))
print ("Name: {} marks: {}".format(s2.name, s2.marks))

它将生成以下 output

Name: Rajaram marks: 50
Name: Bharat marks: 25

在上面的示例中,实例变量在类内初始化。但是,从类外部访问实例变量值没有限制,这违背了封装原则。

尽管没有用于强制可见性的关键字,但 Python 有以特殊方式命名实例变量的约定。在 Python 中,使用单下划线或双下划线作为变量/方法名的前缀来模拟受保护和私有访问修饰符的行为。

如果某个变量的前缀为单个双下划线(如“ __age ”),则该实例变量为私有变量,类似地,如果某个变量名的前缀为单个下划线(如“ _salary ”)

Example 2

让我们修改 Student 类。添加另一个实例变量salary。通过给 name 和 marks 加上前缀双下划线,将它们变为私有。

class Student:

   def __init__(self, name="Rajaram", marks=50):
      self.__name = name
      self.__marks = marks
   def studentdata(self):
      print ("Name: {} marks: {}".format(self.__name, self.__marks))

s1 = Student()
s2 = Student("Bharat", 25)

s1.studentdata()
s2.studentdata()
print ("Name: {} marks: {}".format(s1.__name, s2.__marks))
print ("Name: {} marks: {}".format(s2.__name, __s2.marks))

当您运行此代码时,它将生成以下 output

Name: Rajaram marks: 50
Name: Bharat marks: 25
Traceback (most recent call last):
 File "C:\Python311\hello.py", line 14, in <module>
  print ("Name: {} marks: {}".format(s1.__name, s2.__marks))
AttributeError: 'Student' object has no attribute '__name'

上述输出明确指出了实例变量 name 和 age 可由类内声明的方法(studentdata() 方法)访问,但双下划线前缀使变量为私有变量,因此,限制了在类外部访问这些变量,这会引发属性错误。

What is Name Mangling?

Python 并没有完全阻止对私有数据的访问。它只是将此操作委托给编程人员的智慧,而不是编写从类外部访问这些变量的任何代码。你仍可以通过 Python 的名称混淆技术来访问私有成员。

名称混淆是将双下划线成员的名称更改为 object._class__variable 格式的过程。如果需要,仍然可以从类外访问它,但应该避免此做法。

在我们的示例中,私有实例变量 "__name" 被改写为格式以得到破坏

obj._class__privatevar

因此,要访问“s1”对象的“_marks”实例变量的值,请将其更改为“s1._Student_marks”。

将上面程序中的 print() 语句更改为 −

print (s1._Student__marks)

它现在打印 s1 的分数 50。

因此,我们可以得出结论,Python 并非完全按照面向对象编程的理论来实现封装。它通过规定一个命名约定并允许编程人员在确实需要在 public 范围内访问私有数据时使用名称混淆,采用了更加成熟的做法。