python _单下划线与__双下划线变量引用


python2.7,突然对_和__开头的变量产生了兴趣,这里记录一下。并不包含__xx__的变量

_和__的区别

  以_与__开头的变量是特殊的变量,简单的说:
  模块内:
    _单下划线的变量可以被实例使用(即实例名._变量),也可以被类使用(即可通过类名._变量使用),继承后可以被重写
    __双下划线的变量不可被实例使用(实例名.__变量报错),在类内部可以被类使用,在类外部不能被类使用,继承后重写无效,可以理解为不能被继承
  模块外:
    使用命名空间的引用(即import 模块 或者 from xx import 模块),通过模块._变量访问,同模块内规则
    使用*的引用(from xx import * ),除非__all__中指明,否则带下划线的变量都不能使用

例子

class A:
    _arg=0                  #_单下划线变量
    __arg=0;                #__双下划线变量
    def _fn(self):          #_单下划线方法
        return '_fn'
    def __fn(self):         #__双下划线方法
        return '__fn'
    def p_fn(self):
        return self._fn()   #类内部,使用_单下划线方法
    def p__fn(self):
        return self.__fn(); #类内部,使用__双下划线方法
    def getArg(self):
        return self.__arg;  #在类内部,__双下划线变量可以使用  self.   使用,实例本身没有定义同名变量的情况下,会引用类的该同名变量
    def getArg2(self):
        return A.__arg;     #在类内部,__双下划线变量可以使用  类名. 使用
    #以下为实例自身的__双下划线变量赋值和取值,类似于java中的private变量了
    def getpri(self):
        return self.__pri;  
    def setpri(self,val):
        self.__pri=val 


class B(A):
    '''继承A类'''
    def _fn(self):
        '''可以重写_单下划线方法'''
        return 'B_fn'
    def __fn(self):
        '''不可重写__双下划线,这样写不会报错,但继承来的A中的方法调用的还是A中的__fn,重写的__fn只在B类下才可调用'''
        return 'B__fn'
    def get__fn(self):
    	'''调用子类B自身的__双下划线变量,并且,子类不能直接使用self.来调用父类A中的__双下划线变量!!'''
        return self.__fn()
 


a=A()
print a.p_fn(),'实例调用,可在类的其他方法内调用_单下划线变量'#输出 _fn
print a.p__fn(),'实例调用,可在类的其他方法内调用__双下划线变量'#输出 __fn
print a._fn(),a._arg,'实例调用,可直接调用__单下划线变量,使用pycharm时并未给出该方法和变量的联想,但可以使用'#输出 _fn 0
# print a.__fn(),'实例调用,报错'
# print a.__arg,'实例调用,报错'
print A._arg,'类调用,可以使用_单下划线变量pycharm也没有给出联想'#输出 0
# print A.__arg,'类调用,报错'
print A._fn(a),'类调用,可以使用_单下划线变量pycharm也没有给出联想'#输出 _fn
b=B()
print b.p_fn(),'实例调用,可以看见输出的内容被重写'#输出 B_fn
print b.p__fn(),'实例调用,可以看见输出的内容未被重写,实际上是继承自A类的方法调用了A类的__fn方法'#输出 __fn  #如果被重写,应该输出   B__fn
print b.get__fn(),'输出自己__fn方法'#输出B_fn
a.setpri(3)
print a.getpri()		#输出3
print a.__pri			#报错,该变量确实为private变量
c=A()
c.setpri(9)
print c.getpri()		#输出9,优先使用实例的同名变量,

hasattr()函数在类及实例中无法判断__双下滑线变量是否存在

  在写单例模式练手的时候发现,对于__双下划线的变量虽然能够对外隐藏,但对内使用hasattr函数总返回不存在,debug发现__双下滑线在实例中以 _类名__变量名 (A类的__d变量则存为 _A__d)的形式存在;

class A:
    __d=00
    def set(self):
        self.__arg={1:1}
    def get(self):
        return hasattr(self,'_A__arg')
a=A()
print hasattr(a,'__d'),'直接判断__d是否存在'	#输出False,判断失败
print hasattr(a,'_A__d'),'判断_A__d是否存在'	#输出True
print a.get(),'赋值前'	#输出False
a.set()
print a.get(),'赋值后'	#输出True
b=A()
print b.get(),'__双下划线私有变量也是可以跟实例,此处新的实例未赋值,仍旧为False'
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值