CodeGym /Java 课程 /Python SELF ZH /特殊方法和字段

特殊方法和字段

Python SELF ZH
第 15 级 , 课程 5
可用

5.1 访问级别

你可能注意到构造函数的名字有点奇怪,像__init__? 将来你会经常看到这样的东西。

在Python中,有不同的访问级别来控制类的属性和方法的可见性和数据保护。主要的访问控制机制包括在属性或方法名前使用一个或两个下划线(___)。

使用约定

单个下划线 _用于类或模块内部使用的属性和方法。这并不是禁止使用,但这是一个需要遵循的约定,以提高代码的可读性和维护性。

双下划线 __用于那些真正需要私有和保护的属性和方法,不想被无意或故意地从外部访问。name mangling机制使它们不那么容易访问,但仍然可通过特殊名称访问。

公共(public)字段和方法

公共属性和方法 可以从代码的任何地方访问。在 Python中,默认情况下所有属性和方法都是公共的,除非它们的名字以下划线开始。


class MyClass:
    def __init__(self):
        self.public_attribute = "I am public"
        
    def public_method(self):
        return "This is a public method"
        

obj = MyClass()
print(obj.public_attribute)  # 可访问
print(obj.public_method())  # 可访问

通过Python中的访问级别实现 封装,主要通过不公开的字段和方法。

5.2 非公开字段和方法

保护(protected)字段和方法

受到保护的属性和方法之前用一个下划线_来表明,主要用于类和其子类的内部使用。这是一个告诉程序员这些数据不应该在类外部使用的约定。


class MyClass:
    def __init__(self):
        self._protected_attribute = "I am protected"
        
    def _protected_method(self):
        return "This is a protected method"
        

obj = MyClass()
print(obj._protected_attribute)  # 可访问,但不推荐
print(obj._protected_method())  # 可访问,但不推荐

私有(private)字段和方法

在Python中,私有属性和方法在名字前用两个下划线__表示。它们专用于类内部使用,主要目的是隐藏内部实现和保护数据免受外部的无意修改或使用。

为了防止从外部代码直接访问这些属性和方法,Python采用了一种称为name mangling(名字混淆)的特殊机制。这个机制会自动改变私有属性的名字,在它们前加上一个类名前缀。因此,类MyClass中的私有属性__private_attribute会被转换为内部名字_MyClass__private_attribute

这为保护数据免受不小心的访问提供了保障,同时仍然允许在类内部使用这些数据。然而,要记住,"name mangling"机制不是绝对的保护措施——有经验的程序员可以通过改变的名字来访问这些数据。

让我们看看这个在实践中是如何工作的:


class MyClass:
    def __init__(self):
        self.__private_attribute = "I am private"
        
    def __private_method(self):
        return "This is a private method"
        
    def access_private_method(self):
        return self.__private_method()
         

obj = MyClass()
# print(obj.__private_attribute)  # 错误,不可直接访问
# print(obj.__private_method())  # 错误,不可直接访问
print(obj.access_private_method())  # 通过类的公共方法访问

正如例子中所见,直接访问私有属性或方法会产生错误。但Python允许通过改变的名字访问它们。例如,你可以使用“改变”的名字访问私有属性,如下所示:


class MyClass:
    def __init__(self):
        self.__private_attribute = "I am private"
   
obj = MyClass()
print(obj._MyClass__private_attribute)  # 输出: I am private

虽然通过“改变”的名字访问是可能的,但应该避免这样做,因为它违反了封装原则,可能导致代码不稳定。

为了查看Python如何改变属性名字,你可以使用内置函数dir(),它显示对象的所有可访问属性和方法:


class MyClass:
    def __init__(self):
        self.__private_attribute = "I am private"
   
obj = MyClass()
print(dir(obj))  # 显示对象的所有属性和方法,包括“改变”的名字

dir()函数运行的结果中,你会看到对象的所有属性和方法列表,包括_MyClass__private_attribute,这证实了"name mangling"机制的存在。

5.3 自动调用方法

在使用构造函数时,有一个有趣的方面,你可能注意到了。__init__方法会自动调用。

其实这样的情况有很多,同样有很多方法在这些情况下会被调用。比如:

方法__str__

如果你的对象有__str__方法,那么在试图将对象转换为字符串时,它会自动被调用,例如使用print()str()函数时。


class Cat:
    def __init__(self, name, age):
        self.name = name
        self.age = age
            
    def __str__(self):
        return f"{self.name} is {self.age} years old"
            

cat = Cat("Barsik", 5)
print(cat)  # 输出: Barsik is 5 years old

方法__len__

如果你的对象有__len__方法,当试图获取你的对象的“长度”时,它会自动被调用——这是通过len()函数实现的。例如:


class MyList:
    def __init__(self, items):
        self.items = items
        
    def __len__(self):
        return len(self.items)
        
        
my_list = MyList([1, 2, 3])
print(len(my_list))  # 输出: 3

此类“特殊方法”在你的人生中会有很多,但使用它们是一种乐趣。所以准备好:)

评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION