Python 私有变量

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

1.定义私有变量

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

class C:  #定义类C
	def __init__(self,x): #定义带参构造函数
		self.__x = x  #定义私有变量
	def set_x(self,x): #定义set_x方法,设置私用变量的值
		self.__x = x
	def get_x(self):   #定义get_x方法,获取私有变量的值
		print(self.__x)

		
c = C(22)
c.__x   #从外部访问私有变量会报错
'''
Traceback (most recent call last):
  File "<pyshell#16>", line 1, in <module>
    c.__x
AttributeError: 'C' object has no attribute '__x'
'''
c.get_x() #调用内部方法,访问私有变量
# 22
c.set_x(33)
c.get_x()
# 33

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

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

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

c._C__x
# 33

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

class Si:
	def __funA(self): #定义私有方法
		print("我是私有方法")

		
s = Si()
s.__funA()
'''
Traceback (most recent call last):
  File "<pyshell#34>", line 1, in <module>
    s.__funA()
AttributeError: 'Si' object has no attribute '__funA'
'''
s._Si__funA() #强访问
# 我是私有方法

2. 动态添加属性

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

c.__y = 250 向实例对象中添加数据
c.__dict__

# {'_C__x': 22, '__y': 250}

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

3. 与下划线相关的变量

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

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

 def funA():
	for_ = 100
	print(for_)

	
funA()


# 100

4. 效率提升 __slots__

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

class A:                     #定义类A
	def __init__(self,x):    #构造方法__init__
		self.x = x


a = A(10)                    #对x进行赋值
a.x
# 10                         
a.y = 20                     #向实例对象中添加属性y 
a.y
# 20
a.__dict__                   #查看实例对象中的属性值
# {'x': 10, 'y': 20}

a.__dict__['z'] = 30         #向实例对象中添加不存在的属性 z
a.z
# 30
a.__dict__
# {'x': 10, 'y': 20, 'z': 30} 

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

class B:
	 __slots__["x","y"]      #限制该类中只能定义 x和y属性
	 def __init__(self,x):
		 self.x = x

b = B(20)
b.x
# 20
b.y = 30
b.y
# 30
b.z = 40             #像实例对象中加入__slots__中没有规定的数据时,会报错

#'B' object has no attribute 'z'

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

class B:
	 __slots__["x","y"]      #限制该类中只能定义 x和y属性
	 def __init__(self,x,y,z):
		 self.x = x
         self.y = y
         self.z = z

b = B(20,30,40)
          
#'B' object has no attribute 'z'

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

5.继承中的__slots__

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

class B:
	 __slots__["x","y"]      #限制该类中只能定义 x和y属性
	 def __init__(self,x):
		 self.x = x

class C(B):  #定义类C,继承类 B
   pass

c = C(20)
c.x
# 20
c.y = 30
c.y
# 30
c.z = 40 #定义继承类中不存在的属性
c.z
# 40        可以输出创建的属性值
c.__slots__
# ['x','y']
c.__dict__
# {'z',40}

    

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

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

学者山羊

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

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

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

打赏作者

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

抵扣说明:

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

余额充值