找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

2924

积分

0

好友

390

主题
发表于 前天 10:32 | 查看: 13| 回复: 0

掌握Python中的访问控制机制,是深入理解面向对象编程不可或缺的一环。无论是公有(Public)、保护(Protected)还是私有(Private)属性,它们如何在内部存储与访问,常常困扰着初学者。今天,我们就通过几个循序渐进的练习,来揭开这些属性在类实例中的真实面貌。

练习51:实例化与属性映射

实现一个名为 Laptop 的类,在创建实例时设置以下实例属性:

  • brand 作为公有实例属性
  • model 作为受保护属性
  • price 作为私有属性

然后创建一个名为 laptop 的实例,具有以下参数:

  • 'Acer'
  • 'Predator'
  • 5490

作为响应,打印 laptop 实例的 __dict__ 属性值。

预期结果:

{'brand': 'Acer', '_model': 'Predator', '_Laptop__price': 5490}

想要完成这个练习,我们需要理解Python中受保护属性和私有属性的命名约定。受保护属性通常以一个下划线 _ 开头,而私有属性则以双下划线 __ 开头。实例的 __dict__ 属性会返回一个包含其所有实例属性和对应值的字典,从中我们可以直观地看到这些属性在内部的实际存储名称。

根据要求,我们可以这样实现类:

class Laptop:
    def __init__(self, brand, model, price):
        self.brand = brand
        self._model = model
        self.__price = price

laptop = Laptop('Acer', 'Predator', 5490)
print(laptop.__dict__)

运行这段代码,你将得到与预期一致的结果。注意观察私有属性 price__dict__ 中是如何被“名称修饰”(Name Mangling)为 _Laptop__price 的。

练习52:访问不同可见性的属性

继续使用上面实现的 Laptop 类。然后,使用以下参数创建 Laptop 类的一个名为 laptop 的实例:

  • 'Acer'
  • 'Predator'
  • 5490

作为响应,按如下所示打印 laptop 实例的每个实例属性值(每行一个)。

预期结果:

brand -> Acer
model -> Predator
price -> 5490

这个练习的关键在于如何正确地访问私有属性。公有属性 brand 可以直接通过 laptop.brand 访问,受保护属性 model 可以通过 laptop._model 访问(尽管约定上不建议在类外部直接访问)。那么私有属性 price 呢?根据上一个练习的发现,我们需要使用被修饰后的名称 _Laptop__price

因此,代码实现如下:

class Laptop:
    def __init__(self, brand, model, price):
        self.brand = brand
        self._model = model
        self.__price = price

laptop = Laptop('Acer', 'Predator', 5490)
print(f'brand -> {laptop.brand}')
print(f'model -> {laptop._model}')
print(f'price -> {laptop._Laptop__price}')

执行后,你就能成功输出所有属性的值。这清晰地展示了私有属性的访问方式,它并非完全不可访问,而是通过一个特定的、与类名关联的名称来实现的。

练习53:筛选并显示私有属性

给出了 Laptop 类的 __init__ 方法实现如下:

def __init__(self, brand, model, code, price, margin):
    self.brand = brand
    self._model = model
    self._code = code
    self.__price = price
    self.__margin = margin

现在,需要在 Laptop 类中实现一个名为 display_private_attrs() 的方法,该方法显示实例的所有私有属性名称。然后使用以下参数创建一个实例:

  • 'Acer'
  • 'Predator'
  • 'AC-100'
  • 5490
  • 0.2

并将其赋值给变量 laptop。作为响应,在 laptop 实例上调用 display_private_attrs()

预期结果:

_Laptop__price
_Laptop__margin

这个练习要求我们编写一个方法来自动识别私有属性。思路是遍历实例的 __dict__,找出那些经过名称修饰的属性。在 Python 中,私有属性的修饰规则是在属性名前加上 _类名

所以,我们可以这样实现 display_private_attrs 方法:

class Laptop:
    def __init__(self, brand, model, code, price, margin):
        self.brand = brand
        self._model = model
        self._code = code
        self.__price = price
        self.__margin = margin

    def display_private_attrs(self):
        for attr in self.__dict__:
            if attr.startswith('_'+self.__class__.__name__+'_'):
                print(attr)

laptop = Laptop('Acer', 'Predator', 'AC-100', 5490, 0.2)
laptop.display_private_attrs()

该方法会检查 __dict__ 中的每个键(属性名),如果它是以 _Laptop_ 开头的,则判定为私有属性并打印出来。

练习54:筛选并显示受保护属性

给出了 Laptop 类的 __init__ 方法实现如下:

class Laptop:
    def __init__(self, brand, model, code, price, margin):
        self.brand = brand
        self._model = model
        self._code = code
        self.__price = price
        self.__margin = margin

Laptop 类中实现一个名为 display_protected_attrs() 的方法,该方法显示实例的所有受保护属性名称。然后使用以下参数创建一个实例:

  • 'Acer'
  • 'Predator'
  • 'AC-100'
  • 5490
  • 0.2

并将其赋值给变量 laptop。作为响应,在 laptop 实例上调用 display_protected_attrs()

预期结果:

_model
_code

这个练习与上一个类似,但目标是筛选受保护属性。受保护属性的命名约定是:以一个下划线 _ 开头,但并非以双下划线 __ 开头(除非是像 __init__ 这样的特殊方法,但它们通常不存储在 __dict__ 里)。

因此,我们的判断逻辑是:属性名以 _ 开头,且不以 __ 开头。注意,我们也需要排除那些私有属性(即以 _类名__ 开头的),因为它们也符合“以 _ 开头”的条件。

实现代码如下:

class Laptop:
    def __init__(self, brand, model, code, price, margin):
        self.brand = brand
        self._model = model
        self._code = code
        self.__price = price
        self.__margin = margin

    def display_protected_attrs(self):
        for attr in self.__dict__:
            # 以一个下划线开头,并且不是以“_类名__”这种私有属性格式开头
            if attr.startswith('_') and not attr.startswith('__' + self.__class__.__name__ + '__'):
                print(attr)

laptop = Laptop('Acer', 'Predator', 'AC-100', 5490, 0.2)
laptop.display_protected_attrs()

运行后,将正确地输出 _model_code

通过以上四个循序渐进的练习,我们不仅动手编写了代码,还深入探究了Python中不同类型属性的内部存储机制和访问方式。理解这些细节,能帮助你在未来的后端与架构设计和类封装中做出更明智的决策。如果想与更多开发者交流类似的心得或挑战,欢迎来云栈社区一起探讨。




上一篇:Linux LVM实战排错指南:14个常见存储故障场景与解决
下一篇:苹果扫货移动DRAM致供应链震动,安卓阵营承压或面临涨价潮
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-4-7 18:36 , Processed in 0.579824 second(s), 39 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表