博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Python基础(二十二): 属性的访问权限
阅读量:7049 次
发布时间:2019-06-28

本文共 4482 字,大约阅读时间需要 14 分钟。

  1. 属性的访问权限: 公有属性、受保护的属性、私有属性
  2. Python中并没有真正的私有化支持, 但是可以使用下划线, 完成伪私有的效果

一、公有属性

  • 公有属性
* 类内部访问* 子类内部访问* 模块内其他位置: 父类, 派生类, 父类实例, 派生类实例* 跨模块访问: import, from 模块 import *复制代码

1、类内部访问

class Animal:    name = "旺财"    def call(self):        print(Animal.name)        print(self.name)a = Animal()a.call()# 打印结果:旺财旺财复制代码

2、子类中访问

class Animal:    name = "旺财"    class Dog(Animal):    def call(self):        print(Dog.name)        print(self.name)d = Dog()d.call()# 打印结果:旺财旺财复制代码

3、模块内其他位置访问

  • 父类, 派生类
class Animal:    name = "旺财"    class Dog(Animal):    pass    print(Animal.name)print(Dog.name)# 打印结果:旺财旺财复制代码
  • 父类实例, 派生类实例
class Animal:    name = "旺财"    class Dog(Animal):    passa = Animal()d = Dog()print(a.name)print(d.name)# 打印结果:旺财旺财复制代码

4、跨模块访问类的属性

  • 在其他模块中导入使用, 假设本模块名字为Module

  • import 模块名

import Modulepirnt(Module.Animal.name)       # 打印: 旺财复制代码
  • from 模块名 import *
from Python import *print(Animal.name)              # 打印: 旺财复制代码

5、跨模块访问变量

  • 在模块Module内定义一个变量
a = 10复制代码
  • import 模块名: 跨模块访问Module中的变量a
import Modulepirnt(Module.a)       # 打印: 10复制代码
  • from 模块名 import *: 跨模块访问Module中的变量a
from Python import *print(a)              # 打印: 10复制代码

二、受保护的属性

  • 受保护的属性: 在定义属性时, 在名称前面加上一个下划线_
* 类内部访问* 子类内部访问* 模块内其他位置: 父类, 派生类, 父类实例, 派生类实例, 但是会有警告* 跨模块访问: import 模块: 可以访问, 但是会有警告            from 模块 import *: 可以访问, 但是会有警告复制代码

1、类内部访问

  • 正常访问, 没有警告
class Animal:    _name = "富贵"    def call(self):        print(Animal._name)        print(self._name)a = Animal()a.call()# 打印结果:富贵富贵复制代码

2、子类内部访问

  • 正常访问, 没有警告
class Animal:    _name = "富贵"class Dog(Animal):    def call(self):        print(Dog._name)        print(self._name)d = Dog()d.call()# 打印结果:富贵富贵复制代码

3、模块内其他位置

  • 父类、派生类访问, 会有警告
class Animal:    _name = "富贵"    class Dog(Animal):    pass;    print(Animal._name)print(Dog._name)# 打印结果:富贵富贵# 警告: Access to a protected member _name of a class复制代码

正常打印, 但是会发出警告: Access to a protected member _name of a class

  • 父类实例、派生类实例访问, 会有警告
class Animal:    _name = "富贵"    class Dog(Animal):    pass;    a = Animal()d = Dog()print(a._name)print(d._name)# 打印结果:富贵富贵# 警告: Access to a protected member _name of a class复制代码

正常打印, 但是会发出警告: Access to a protected member _name of a class

4、跨模块访问类的属性

  • 在其他模块中导入使用, 假设本模块名字为Module

  • import 模块名: 可以访问, 但是会有警告

import Moduleprint(Module.Animal._name)        # 打印: 10# 警告: Access to a protected member _name of a class复制代码
  • from 模块名 import *: 可以访问, 但是会有警告
from Module import *print(Animal._name)# 警告: Access to a protected member _name of a class复制代码

5、跨模块访问变量

  • 假设模块Module中有一个变量
_a = 10复制代码
  • import 模块名: 可以访问, 但是会有警告
import Moduleprint(Module._a)        # 打印: 10# 警告: Access to a protected member _a of a module复制代码
  • from 模块名 import *: 不可以访问, 报错
from Module import  *print(_a)               # 报错: NameError: name '_a' is not defined复制代码

5、__all__

  • __all__: 表示其他模块使用本模块式时, 可以导入的变量, 在默认情况下, 如果变量前有一个下划线_, 例如:_a, 就不会存放在__all__
  • 我们在__all__中加上_a, 就可以在其他模块中使用_a
# Module模块__all__ = ["_a"]_a = 10复制代码
# 其他模块from Module import  *print(_a)               # 打印: 10复制代码

三、私有属性

  • 私有属性: 只能在类的内部访问
* 类内部访问* 子类不能访问* 模块内其他位置不能访问* 跨模块不能访问复制代码

1、类内部访问

class Animal:    __name = "狗蛋"    def call(self):        print(Animal.__name)        print(self.__name)a = Animal()a.call()# 打印效果:狗蛋狗蛋复制代码

2、私有属性的实现机制

  • 私有属性的实现机制 -- 名字重整(Name Mangling)

  • 解释器会将带有两个下划线__的属性的名字修改, 例如_类名__x

class Aminal:    __name = "狗蛋"复制代码
  • 可以通过类的__dict__属性, 查看类中的属性
print(Animal.__dict__)# 打印: {'__module__': '__main__', '_Animal__name': '狗蛋', '__dict__': 
, '__weakref__':
, '__doc__': None}复制代码
  • 可以看到有一个属性的名字叫_Animal__name, 我们可以直接在类的外面访问它
print(Animal._Animal__name)         # 打印: 狗蛋复制代码

名字重整的目的: 防止外界直接访问, 防止被子类同名称属性覆盖

模块内带有两个下划线的变量与只有一个下划线的变量使用方法一致, 不再测试

3、私有属性一个简单的应用场景

  • 定义一个Person类, 并在初始化方法中添加私有属性__age
class Person:    def __init__(self):        self.__age = 0复制代码
  • 因为私有属性是不暴露给外界的, 所以在赋值和取值的时候, 需要定义两个方法
def setAge(self, value):    self.__age = value    def getAge(self):    return self.__age复制代码
  • 因为__age描述的是人的年龄, 所以必须是int类型, 且在0-200之间
def setAge(self, value):    if isinstanse(value, int) and 0 < value < 200:        self.__age = value复制代码
  • 完整代码如下:
class Person:    def __init__(self):        self.__age = 0            def setAge(self, value):        if isinstance(value, int) and 0 < value < 200:            self.__age = value                def getAge(self):        return self.__age复制代码
  • 在赋值和取值时, 直接调用方法就可以了
p = Person()p.setAge(20)            # 赋值age = p.getAge()        # 取值print(age)              # 打印: 20复制代码

补充: 关于属性命名时加下划线的规范问题

  1. 在名字后面添加一个下划线, 用于与系统关键词区分, 例如: class_
  2. 系统内键属性, 两端各加两个下划线, 例如: __dict__, 我们给变量命名时应该避免这种命名方式, 与系统区分开

转载地址:http://yrpol.baihongyu.com/

你可能感兴趣的文章
各种实用工具的使用 学习
查看>>
MarkLight
查看>>
显示/隐藏Mac下的隐藏文件
查看>>
关于数字签名简要原理
查看>>
POJ-3565 Ants 空间点对不相交匹配-最小权值匹配
查看>>
第三次月考
查看>>
单例模式的理解与应用
查看>>
springmvc(一)
查看>>
Hibernate与 MyBatis的比较
查看>>
【51NOD-0】1137 矩阵乘法
查看>>
Android使用静默安装时碰见的问题
查看>>
MySQL单机多实例安装并配置主从复制
查看>>
awk调用shell命令的两种方法:system与print
查看>>
网络对抗技术 20164320 王浩 Exp 9 Web安全基础
查看>>
谷歌开源第二代机器学习系统 TensorFlow
查看>>
juqery模板 Templates
查看>>
eclipse 自动创建web.xml
查看>>
python 基础回顾2
查看>>
Servlet 示例
查看>>
十一.单表更新及多表更新
查看>>