关于类中__隐藏

文章讲述了在Python编程中,关于类继承时遇到的属性名称修饰问题,解释了双下划线开头的属性并非真正的私有,以及如何通过名称修饰访问和修改父类隐藏属性的方法。
摘要由CSDN通过智能技术生成

今天在修正别人代码中,碰到一个问题,大概demo是下面的

class Index:
    def __init__(self):
        self.__number = None

    def create_number(self):
        self.__number = 3

    def print_number(self):
        print(self.__number, '父类的')


class Inner(Index):
    def __init__(self):
        # 这里为什么没用super,我也不知道为什么,上个人这么写的
        self.__number = None
        print('这里也重写了一部分')

    #
    def create_number(self):
        self.__number = 3
        print('这里重写了某一部分')

    def send_number(self):
        print(self.__number, '子类的')


obj = Inner()
obj.create_number()
obj.print_number()
obj.send_number()

乍一看代码逻辑上面没有问题,但是当我程序真正执行的时候发现了直接报错了,错误显示:

AttributeError: 'Inner' object has no attribute '_Index__number'. Did you mean: '_Inner__number'?

告诉我们Inner的object没有 _Index__number这个属性,我发现我也没有定义这个属性呀,后来我修改了一下,代码改为下面这样就正常的了

class Index:
    def __init__(self):
        self.__number = None

    def create_number(self):
        self.__number = 3

    def print_number(self):
        print(self.__number, '父类的')


class Inner(Index):
    def __init__(self):
        # 这里为什么没用super,我也不知道为什么,上个人这么写的
        self.__number = None
        print('这里也重写了一部分')

    #
    def create_number(self):
        super().create_number()

    def send_number(self):
        print(self.__number, '子类的')


obj = Inner()
obj.create_number()
obj.print_number()  # 3 父类的
obj.send_number()   # None 子类的

这样他就正常了,后面的方法也可以成功调用,但是我们看打印,我在子类和父类中都有一个属性叫__number这个属性,但是打印的时候调用过了create_number函数,显示的结果确不一样,父类的改为了3,子类的还是None,就小小的好奇了一下是什么原因

之前碰到的__开头我们都知道在python中是隐藏的意思,但是又记得不是真正的隐藏,所以找了一下,是我自己概念出现了错误

解释大概是这样的:

在 Python 中,以双下划线 __ 开头的属性会被进行名称修饰(name mangling),变成 _ClassName__attribute 的形式。这个机制是为了防止子类意外地覆盖同名的父类属性,而不是为了实现真正意义上的隐藏。

虽然这种机制可以增加对属性的访问控制,但它并不是真正意义上的私有化。事实上,在 Python 中没有严格意义上的“私有”属性或方法,因为 Python 支持动态访问对象的属性和方法。

即使一个属性以双下划线开头,仍然可以通过名称修饰的方式访问到它,尽管这并不是一种推荐的做法。这也意味着,Python 中的封装和访问控制依赖于约定和规范,而不是语言层面的强制性规定。

他会被名称修饰掉,所以我们__开头的属性其实是已经被python解释器改了名字,可以确认一下是否是真的

print(vars(obj))  # {'_Inner__number': None, '_Index__number': 3}

 我们可以看到对象的属性虽然我们肉眼看上去是一个,实际上已经是两个属性了,我们在子类中.__number其实是_Inner__number,而到了父类中.__number其实是_Index__number,所以会出现这样的情况,那么我们想在子类中修改父类的隐藏方法其实就可以通过下面实现

class Index:
    def __init__(self):
        self.__number = None

    def create_number(self):
        self.__number = 3

    def print_number(self):
        print(self.__number, '父类的')


class Inner(Index):
    def __init__(self):
        # 这里为什么没用super,我也不知道为什么,上个人这么写的
        self.__number = None
        print('这里也重写了一部分')

    #
    def create_number(self):
        self.__number = 3
        self._Index__number = 5

    def send_number(self):
        print(self.__number, '子类的')


obj = Inner()
obj.create_number()
print(vars(obj)) 
obj.print_number()  # 5 父类的
obj.send_number()  # 3 子类的

可以通过这样的方式直接访问到父类的隐藏属性进行修改

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值