概要

在基类的定义中,如果有些属性或者方法,我们希望隐藏它,从而不被子类继承,或者使其不被实例直接访问到,这时候可以用到私有属性的命名方法。尽管类的所有属性和方法在某种意义上说都是“暴露的”,但是私有属性的存在即表达了我们的态度。

 


私有属性命名规则

在类中所有以双下划线开头的名称都会自动变形,比如一个私有属性名为 __print,会自动变形为 _Classname__print,这样就有效避免了在子类中使用的私有名称不会与基类中使用的相同私有名称发生冲突。示例代码如下:

# -*- coding: utf-8 -*-

class Marvel(object):
def __init__(self):
self.signature = self.__print()
def __print(self): # 私有实例方法,变形为 _Marvel__print
return "I love Marvel movies!" class EvilMarvel(Marvel):
def __init__(self):
super().__init__()
self.signature = self.__print()
self.base_signature = self.__base_print()
def __print(self): # 私有实例方法,变形为 _DC__print
return "I love DC movies!"
def __base_print(self):
return self._Marvel__print() # 强制调用父类的私有方法 a = Marvel()
print(a.signature) # 输出 I love Marvel movies!
print(a.__print()) # NameError: name '_Marvel__print' is not defined
print(a._Marvel__print()) # 强制访问,输出 I love Marvel movies! b = EvilMarvel()
print(b.signature) # 输出 I love DC movies!
print(b.base_signature) # 输出 I love Marvel movies!

尽管上述两个类别都有 __print 方法,实际调用时不会发生冲突,因为它们都在本身所属的类别中进行变形。当然,我们也可以强制性调用父类中的私有方法,比如 EvilMarvel 中的方法 __base_print,或者从外部强制访问私有属性,比如上述代码中倒数第五行,虽然语法上没任何问题,但是不建议这么做,这种做法也背离了设置私有属性的初衷。

 

单下划线在模块中的作用

单下划线在模块方法中也表示“私有”定义的命名,但它是防止通过 from moddule import * 语句导出名称,比如我们将上个示例代码中子类 EvilMarvel 前加一个下划线,并将文件名命名为 Marvel,再新建一个包含如下代码的文件,调用 _EvilMarvel 时会发生错误,

from Marvel import *

a = _EvilMarvel()
print(a.signature) # NameError: name '_EvilMarvel' is not defined

注意如果显示地引用单下划线开头的方法,则是可以的,比如

from Marvel import _EvilMarvel

a = _EvilMarvel()
print(a.signature) # 输出 I love DC movies!

另外可以通过定义模块中的列表 __all__,可以精确控制 from moddule import * 导入的名称集合,不过在此不作过多说明。

值得一提的是,这种单下划线的方式在类中,与普通属性名没有任何区别,不要混淆。

 


总结

Python 中的私有属性是一种通过添加双下划线的“伪”方法,这样可以避免父类与子类定义的对象之间发生命名空间冲突和暴露对象的内部实现,以及防止被实例对象直接访问得到,从而增强代码的健壮性。

Python 之私有属性的更多相关文章

  1. python 基础——私有属性

    私有属性 python 私有属性以两个下划线开头. python 私有属性只能在类内部访问,类外面访问会出错. python 私有属性之所以不能在外面直接通过名称来访问,其实质是因为 python 做 ...

  2. python 面向对象 私有属性

    __init__构造函数 self.name = name # 属性, 实例变量,成员变量,字段 def sayhi()# 方法, 动态属性 私有属性不对外看到 前面加上__ class role() ...

  3. python中私有属性的访问

    class MyClass(): def __init__(self): self.__superprivate = "Hello" self.__semiprivate = &q ...

  4. Python面向对象之私有属性和方法

    私有属性与私有方法 应用场景 在实际开发中,对象的某些属性或者方法 可能只希望在对象的内部被使用,而不希望在外部被访问到: 私有属性 就是对象不希望公开的属性: 私有方法 就是对象不希望公开的方法: ...

  5. Python - 私有属性(双下线的变形)

    __x会自动变形为_类名__x 正常情况 class A: def foo(self): print('from A') def test(self): self.foo() class B(A): ...

  6. Python 安全修改私有属性

    设置私有属性之后,如何修改私有属性 class Room: def __init__(self,name,length,width): self.__name = name self.__length ...

  7. Python全栈--9.1--面向对象进阶-super 类对象成员--类属性- 私有属性 查找源码类对象步骤 类特殊成员 isinstance issubclass 异常处理

    上一篇文章介绍了面向对象基本知识: 面向对象是一种编程方式,此编程方式的实现是基于对 类 和 对象 的使用 类 是一个模板,模板中包装了多个“函数”供使用(可以讲多函数中公用的变量封装到对象中) 对象 ...

  8. Python的伪私有属性

    什么是伪私有属性? 在Python中,没有类似 private 之类的关键字来声明私有方法或属性. Python中要声明私有属性,需要在属性前加上双下划线(但是结尾处不能有双下划线),如:self._ ...

  9. python面向对象学习(三)私有属性和私有方法

    目录 1. 应用场景和定义方式 2. 伪私有属性和私有方法 在java或者其他的编程语言中,使用访问修饰符来限制属性和方法的访问级别,一般有public.protected.default.priva ...

随机推荐

  1. SP1716 GSS3

    题意翻译 \(n\) 个数,\(q\) 次操作 操作\(0\) \(x\) \(y\)把\(A_x\) 修改为\(y\) 操作\(1\) \(l\) \(r\)询问区间\([l, r]\)的最大子段和 ...

  2. mariadb yum安装

    安装 yum install mariadb mariadb-server -y 启动 systemctl start mariadb systemctl enable mariadb 安全安装 # ...

  3. Node.js实现TCP和HTTP并作简单的比较

    TCP和Node 传输控制协议是一个面向连接的协议,换句话说,它是一个传输层的协议,它主要的职务呢,就是确保信息传输的正确性. 我们使用的很多如HTTP协议都是基于TCP的,为什么呢?因为我们不希望传 ...

  4. Django---登录(含随机生成图片验证码)、注册示例讲解

    登录(验证码).注册功能具体代码 # urls.py from django.contrib import admin from django.urls import path from app01 ...

  5. BigDecimal默认用四舍五入方式

    import java.math.BigDecimal; target.setWeight(source.getWeight().setScale(3, BigDecimal.ROUND_HALF_U ...

  6. Binary Strings Gym - 101161G 矩阵快速幂 + 打表

    http://codeforces.com/gym/101161/attachments 这题通过打表,可以知道长度是i的时候的合法方案数. 然后得到f[1] = 2, f[2] = 3, f[3] ...

  7. Java ping 主机 端口

    22:04:08.002 [main] INFO Ping - 目标地址 192.168.1.107 是否可到达:true 22:04:08.006 [main] INFO Ping - 执行命令 p ...

  8. ASP.NET Web.Config连接数据库(测试)

    事先说明,我是看着http://jingyan.baidu.com/article/ff411625bc461712e5823775.html做的. web.Config代码(vs2010): 使用的 ...

  9. 网页title旁边的小图片

    网页title旁边的小图片设置,图片格式必须是.ico <link rel="icon" href="img/logo.ico" type="i ...

  10. input和textarea修改placeholder颜色和字号

    方式1因为每个浏览器的CSS选择器都有所差异,所以需要针对每个浏览器做单独的设定(可以在冒号前面写input和textarea).::-webkit-input-placeholder { /* We ...