• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

Python 私有变量

武飞扬头像
学者山羊
帮助1

        所谓私有变量,是指通过某种手段,使得对象中的属性或方法无法被外部所访问。属于Python的保护机制。

1.定义私有变量

        定义私有变量可以在变量名前加上两个 "_",来表示(这里说的私有变量并不是真正的私有,而是尽量避免从外部进行访问)

  1.  
    class C: #定义类C
  2.  
    def __init__(self,x): #定义带参构造函数
  3.  
    self.__x = x #定义私有变量
  4.  
    def set_x(self,x): #定义set_x方法,设置私用变量的值
  5.  
    self.__x = x
  6.  
    def get_x(self): #定义get_x方法,获取私有变量的值
  7.  
    print(self.__x)
  8.  
     
  9.  
     
  10.  
    c = C(22)
  11.  
    c.__x #从外部访问私有变量会报错
  12.  
    '''
  13.  
    Traceback (most recent call last):
  14.  
    File "<pyshell#16>", line 1, in <module>
  15.  
    c.__x
  16.  
    AttributeError: 'C' object has no attribute '__x'
  17.  
    '''
  18.  
    c.get_x() #调用内部方法,访问私有变量
  19.  
    # 22
  20.  
    c.set_x(33)
  21.  
    c.get_x()
  22.  
    # 33
学新通

        上述代码可知,我们从外部访问私有变量会产生错误,因为想访问私有变量的值,就需要通过指定的借口,通过调用内部的方法来实现访问私有变量。如果想从外部访问私有变量,我们可以利用Python的强访问方法—— name mangling机制 ,也就是名字改编。代码如下:

  1.  
    c.__dict__ #通过内省,查看实例对象中的数据
  2.  
    # {'_C__x': 33}

        我们看到会得到{'_C__x': 33}的结果,也就是_类名__私有变量名,我们调用一下可以访问的到私有变量的值。

  1.  
    c._C__x
  2.  
    # 33

        同样的,属性可以通过强访问的方式访问到,方法也是可以的,代码如下:

  1.  
    class Si:
  2.  
    def __funA(self): #定义私有方法
  3.  
    print("我是私有方法")
  4.  
     
  5.  
     
  6.  
    s = Si()
  7.  
    s.__funA()
  8.  
    '''
  9.  
    Traceback (most recent call last):
  10.  
    File "<pyshell#34>", line 1, in <module>
  11.  
    s.__funA()
  12.  
    AttributeError: 'Si' object has no attribute '__funA'
  13.  
    '''
  14.  
    s._Si__funA() #强访问
  15.  
    # 我是私有方法
学新通

2. 动态添加属性

        在对象诞生之后,通过动态添加属性的方式来添加私有变量。

  1.  
    c.__y = 250 向实例对象中添加数据
  2.  
    c.__dict__
  3.  
     
  4.  
    # {'_C__x': 22, '__y': 250}

         通过内省可以看到实例对象中有 __y 这个属性值,并且可以直接访问的到。并没有变成 _C__y 的形式,说明名字改编是发生在类实例化对象的时候的事情,之后添加的属性不会发生改变。

3. 与下划线相关的变量

        一个单横线开头的变量:通常是仅供内部使用的变量,不要随便的访问和试图修改。

        一个单横线结尾的变量:一般用于要定义的变量名是属于Python关键字以及其他内部变量时,强制使用。(其实没啥用~)

  1.  
    def funA():
  2.  
    for_ = 100
  3.  
    print(for_)
  4.  
     
  5.  
     
  6.  
    funA()
  7.  
     
  8.  
     
  9.  
    # 100

4. 效率提升 __slots__

        当我们在实例对象中添加一个不存在的变量的时候,可以借助字典来完成,通过这种方法会很方便的向实例对象中添加数据,不过会浪费大量的存储空间。

  1.  
    class A: #定义类A
  2.  
    def __init__(self,x): #构造方法__init__
  3.  
    self.x = x
  4.  
     
  5.  
     
  6.  
    a = A(10) #对x进行赋值
  7.  
    a.x
  8.  
    # 10
  9.  
    a.y = 20 #向实例对象中添加属性y
  10.  
    a.y
  11.  
    # 20
  12.  
    a.__dict__ #查看实例对象中的属性值
  13.  
    # {'x': 10, 'y': 20}
  14.  
     
  15.  
    a.__dict__['z'] = 30 #向实例对象中添加不存在的属性 z
  16.  
    a.z
  17.  
    # 30
  18.  
    a.__dict__
  19.  
    # {'x': 10, 'y': 20, 'z': 30}
学新通

        这时Python就提供了一个叫做__slots__的类属性,避免了采用字典来存放造成空间上的浪费。采用这个方法可以限制类能使用的属性。

  1.  
    class B:
  2.  
    __slots__["x","y"] #限制该类中只能定义 x和y属性
  3.  
    def __init__(self,x):
  4.  
    self.x = x
  5.  
     
  6.  
    b = B(20)
  7.  
    b.x
  8.  
    # 20
  9.  
    b.y = 30
  10.  
    b.y
  11.  
    # 30
  12.  
    b.z = 40 #像实例对象中加入__slots__中没有规定的数据时,会报错
  13.  
     
  14.  
    #'B' object has no attribute 'z'

        这种限制不仅体现在动态添加属性上面,如果我们想在类的内部创建一个__slots__中不包含的属性,也是不被允许的。

  1.  
    class B:
  2.  
    __slots__["x","y"] #限制该类中只能定义 x和y属性
  3.  
    def __init__(self,x,y,z):
  4.  
    self.x = x
  5.  
    self.y = y
  6.  
    self.z = z
  7.  
     
  8.  
    b = B(20,30,40)
  9.  
     
  10.  
    #'B' object has no attribute 'z'

         __slots__类属性,使对象划分一个固定大小的空间来存放指定的属性,避免了利用字典来存放造成空间上的浪费(列表中的名称 用来限制类使用的属性)。

5.继承中的__slots__

        对于继承在父类的__slots__属性,不会在子类中生效,Python只会关注各个具体的类中定义的__slots__属性。

  1.  
    class B:
  2.  
    __slots__["x","y"] #限制该类中只能定义 x和y属性
  3.  
    def __init__(self,x):
  4.  
    self.x = x
  5.  
     
  6.  
    class C(B): #定义类C,继承类 B
  7.  
    pass
  8.  
     
  9.  
    c = C(20)
  10.  
    c.x
  11.  
    # 20
  12.  
    c.y = 30
  13.  
    c.y
  14.  
    # 30
  15.  
    c.z = 40 #定义继承类中不存在的属性
  16.  
    c.z
  17.  
    # 40 可以输出创建的属性值
  18.  
    c.__slots__
  19.  
    # ['x','y']
  20.  
    c.__dict__
  21.  
    # {'z',40}
  22.  
     
学新通

        对于继承的类中有__slots__属性时,父类中的属性会存放再__slots__中,而子类新添加的属性会存放在__dict__中。

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhghbbge
系列文章
更多 icon
同类精品
更多 icon
继续加载