Python中类的访问限制

学习要点

在Python中,类的访问限制可以通过使用单下划线 _ 和双下划线 __ 进行控制,但这并不是严格的访问控制,而是一种命名约定。

  1. 单下划线 _(约定性私有):

    • 一个下划线前缀表示一个属性或方法应该被视为“内部”使用。这只是一种约定,并没有严格的强制规则。其他程序员应该将以一个下划线开头的属性或方法视为“内部”实现,不建议直接访问。
    • 示例:
      class MyClass:
          def __init__(self):
              self._internal_variable = 42
      
          def _internal_method(self):
              print("This is an internal method.")
      
  2. 双下划线 __(名称改写):

    • 一个双下划线前缀将属性或方法“名称改写”(name mangling)。Python会在名称前面加上一个下划线和类名,以避免子类意外地重写父类的属性或方法。

    • 示例:

      class MyClass:
          def __init__(self):
              self.__private_variable = 42
      
          def __private_method(self):
              print("This is a private method.")
      
    • 请注意,这种机制并不是严格的访问控制,而是一种名称改写,可以通过特定的方式来访问:

      obj = MyClass()
      print(obj._MyClass__private_variable)  # 访问双下划线属性
      obj._MyClass__private_method()  # 访问双下划线方法
      

需要注意的是,这些只是一种约定,Python 并没有严格的访问控制机制。尽管可以通过这些方式来阻止直接访问属性和方法,但在实践中,程序员们通常会遵循一种“不要破坏私有性”的原则,而是信任其他程序员遵循良好的编程实践。

学习测试代码

"""
# -*- coding: utf-8 -*-
# @Time    : 2023/9/20 15:25
# @Author  : 王摇摆
# @FileName: test1.py
# @Software: PyCharm
# @Blog    :https://blog.csdn.net/weixin_44943389?type=blog
"""


# 计算学生的成绩,并得到学生的评级
# 希望内部属性不被外部访问和更改,对私有变量作出调整
class Student(object):
    def __init__(self, name, score):
        self.__name = name
        self.__score = score

    def evaluate(self) -> str:
        """

        @rtype: str
        """
        if self.__score >= 90:
            result = 'A'
        elif self.__score >= 80:
            result = 'B'
        else:
            result = 'C'
        return 'The student is {},his evaluate is {result_final}'.format(self.__name, result_final=result)

    def print_score(self):
        string = f'The student is {self.__name},his score is {self.__score}'
        print(string)

    # 留出私有属性的公有访问方法
    def get_name(self):
        return self.__name

    def get_score(self):
        return self.__score

    def set_name(self, name):
        self.__name = name

    # 最基本的seter方法
    def set_score(self, score: int):
        self.__score = score

    # 高阶的setter方法,可以对传入的参数进行检查
    def set_score_advanced(self, score: int):
        if 0 <= score <= 100:
            self.__score = score
        else:
            raise ValueError('Sry,bad input...,Please input again.')


if __name__ == '__main__':
    wangguowei1 = Student('王国炜1', 100)
    wangguowei2 = Student('王国炜2', 85)
    wangguowei3 = Student('王国炜3', 60)

    wangguowei1.print_score()
    wangguowei2.print_score()
    wangguowei3.print_score()

    print()
    print(wangguowei1.evaluate())
    print(wangguowei2.evaluate())
    print(wangguowei3.evaluate(), end='')

    # 在这里测试getter和setter方法对实例进行更改
    print()
    print(wangguowei1.get_name(), wangguowei1.get_score())
    # wangguowei1.set_score_advanced(110) # 报错不就对了嘛!

    print()
    # 使用特殊方法强制修改私有变量
    wangguowei1._Student__name = 'wangyaobai'
    print(wangguowei1.get_name())
    print(wangguowei1._Student__name)

    # 一种错误的写法
    wangguowei1.__name = "fake name"

    # 看似给类中添加了一个新的变量,但是和类中的属性不是一回事,因为类中本身的属性已被解释器自动翻译成了_Student__name
    print(wangguowei1.__name)
    print(wangguowei1.get_name())
    print(wangguowei1.__name == wangguowei1.get_name())

运行结果

D:\ANACONDA\envs\pytorch\python.exe C:/Users/Administrator/Desktop/Code/Learn_Pyhon3.7/liaoxuefeng/oop/test1.py
The student is 王国炜1,his score is 100
The student is 王国炜2,his score is 85
The student is 王国炜3,his score is 60

The student is 王国炜1,his evaluate is A
The student is 王国炜2,his evaluate is B
The student is 王国炜3,his evaluate is C
王国炜1 100

wangyaobai
wangyaobai
fake name
wangyaobai
False

Process finished with exit code 0

千万要注意的细节问题

  • 弱私有的属性成员,还是能通过实例直接进行修改
  • 强私有的属性成员,不能通过实例进行修改

看似修改成功,但是和实际内存中定义的属性不是一回事

在这里插入图片描述

练习代码

"""
# -*- coding: utf-8 -*-
# @Time    : 2023/9/20 16:49
# @Author  : 王摇摆
# @FileName: practice1.py
# @Software: PyCharm
# @Blog    :https://blog.csdn.net/weixin_44943389?type=blog
"""

"""
请把下面的Student对象的gender字段对外隐藏起来,用get_gender()和set_gender()代替,并检查参数有效性:
"""


class Student(object):
    def __init__(self, name, gender):
        self.__name = name
        self.gender = gender
        self.hobby = 'pingpang'

    def get_gender(self):
        return self.gender

    def set_gender(self, param:str):
        self.gender = param

    def set_name(self, name):
        self.__name = name

    def get_name(self, ):
        return self.__name

print(1)

if __name__ == '__main__':
    # 在正式运行测试代码之前的准备工作
    bart = Student('Bart', 'male')
    print(bart.get_name())
    print(bart.hobby)
    print()

    # 1. 强弱私有属性的测试
    bart.__name = 'wangguowei'
    print(bart.__name)  # 实例私有属性的名字已被解释器转为其他,这里顶多算是定义一个临时共有属性
    print(bart.get_name())
    bart.hobby = 'cf'
    print(bart.hobby)

    # 2. 直接给实例添加临时内容
    bart.university = 'NUC'
    print(bart.university)

    # 3. 作业内容
    print()
    bart.set_name("Bart")

    if bart.get_gender() != 'male':
        print('测试失败!')
    else:
        bart.set_gender('female')
        if bart.get_gender() != 'female':
            print('测试失败!')
        else:
            print('测试成功!')


print(100)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Python,类的访问权限是通过属性和方法的命名约定来实现的,而不是通过关键字或修饰符来定义。Python没有像其他编程语言(如Java或C++)的public、private、protected等关键字来明确指定访问权限。 在Python,有以下几种常用的属性和方法的命名约定来表示访问权限: 1. 公有属性和方法:以单下划线开头(例如:_name),表示该属性或方法是公有的,可以在类的内部和外部访问。 2. 私有属性和方法:以双下划线开头(例如:__name),表示该属性或方法是私有的,只能在类的内部访问。私有属性和方法在类的外部是无法直接访问的,但可以通过特殊的方式进行访问(后面会介绍)。 3. 受保护属性和方法:以单下划线开头(例如:_name),表示该属性或方法是受保护的,只能在类的内部和子类访问。 需要注意的是,这些命名约定并不能真正限制对属性和方法的访问,它们只是一种约定,用于告诉其他开发者应该如何使用这些属性和方法。Python的设计理念是“我们都是成年人”,即相信开发者会遵守这些约定,但并不强制执行。 如果你想在类的外部访问私有属性和方法,可以通过以下方式: 1. 使用单下划线+类名+属性名(例如:_ClassName__name)来访问私有属性。 2. 使用单下划线+类名+方法名(例如:_ClassName__method())来调用私有方法。 这种方式虽然可以访问私有属性和方法,但并不推荐在实际开发使用,因为它破坏了封装性和安全性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

王摇摆

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值