2022年 11月 9日

[转载] Python类中的私有变量和公有变量

参考链接: Python中的私有变量

我们这里就直奔主题,不做基础铺垫,默认你有一些Python类的基础,大家在看这篇博客的时候,如果基础知识忘了,可以去菜鸟教程 

从一个简单的类开始 

class A():       #定义一个类 A

    a     = 100  #公有变量

    _b    = 200  #公有变量

    __c   = 300  #私有变量

    __d__ = 400  #公有变量

a = A()     #实例化一个对象a,当然可以取另外一个名字b

print(a.a,a._b,a.__c,a.__d__)   #打印四个变量的值

 

运行结果: Traceback (most recent call last): File “c:\users\12090\desktop\a.py”, line 7, in  print(a.a,a._b,a.__c,a.d) AttributeError: ‘A’ object has no attribute ‘__c’ 

 

  

   

  

 

运行结果,提示__c不能访问,这里的错误信息,并没有指出__c是私有变量,在类外不能访问 我们程序这样改动  

通过成员函数间接访问私有变量 

 

a=A,和a=A()的区别 

我们把第8行改造一下: 去掉括号,就像这样:  

a = A会成功生成对象a,而且通过对象a可以正确访问到公有变量a,_b,d。但是在调用函数print_c()的时候,出问题,错误提示 TypeError: print_c() missing 1 required positional argument: ‘self’ 提示缺少参数,怎么解决这个问题呢: 显示传递一个类,或者对象进去  那么a=A,和a=A()有什么区别呢? 区别是: 如果是a=A,则不会调用类中的构造函数; 如果是a=A(),则会调用构造函数; 

A()会调用构造函数 

我们来做一个实验, python中的构造函数名是系统规定的,init,添加后如下: 

class A():       #定义一个类 A

    a     = 100  #公有变量

    _b    = 200  #公有变量

    __c   = 300  #私有变量

    __d__ = 400  #公有变量

    def __init__(self):   #构造函数定义

        print(‘calling __init__….’)

    def print_c(self):  #通过成员函数访问私有变量

        return self.__c

a = A          #不会调用构造函数

print(a.a,a._b,a.print_c(a),a.__d__)

b = A()        #会调用构造函数   

print(b.a,b._b,b.print_c(),b.__d__)

 

运行结果:  当我们通过A()这种形式构造对象的时候,会显示调用构造函数__init__。 当我们通过A这种形式构造对象的时候,不会调用构造函数。 

构造函数,构造了什么 

“构造”这个词,是一个动词,就是要造一个东西,那么造什么呢,其实我们上面的例子,可能让初学者有点不明所以,所以接下来,我们让构造函数做点有意义的事情,程序如下: 

class A():       #定义一个类 A

    a     = 100  #公有变量

    _b    = 200  #公有变量

    __c   = 300  #私有变量

    __d__ = 400  #公有变量

    def __init__(self,a,b,c,d):   #通过构造函数给公有变量或者私有变量重新赋值

        print(‘构造前:’,self.a,self._b,self.__c,self.__d__)

        self.a = a

        self._b = b

        self.__c = c

        self.__d__ = d

        print(‘构造后:’,self.a,self._b,self.__c,self.__d__)

    def print_c(self):  #通过成员函数访问私有变量

        return self.__c

a = A(1000,2000,3000,4000)          #通过传值构造对象

 

运行结果:  这个例子,就证明了构造函数的作用 

python中 self的作用 

self这个单词是自己,自我的意思,它代表对象本身,其实你可以换一个单词也可以,比如you  

照样可以运行 甚至一个地方用self,一个地方用you也可以  

self的实际意义 

我们一般使用self,python系统也默认是self,但是self的作用远不止单词意思这么简单 比如我们去掉self  

运行起来,好像也没问题,但是这里的a,_b,__c,d(构造函数里面),并不是公有变量中的a,_b,__c,d。怎么见得呢? 我们把第七行打开  运行结果出错: Traceback (most recent call last): File “c:\users\12090\desktop\a.py”, line 13, in  a = A(1000,2000,3000,4000) #调用构造函数 File “c:\users\12090\desktop\a.py”, line 7, in init print(‘构造前:’,a,_b,__c,d) UnboundLocalError: local variable ‘_b’ referenced before assignment 

错误原因,是本地变量_b没有引用,这个local是本地的意思,也就是在构造函数__init__函数作用范围内。那么第7行的a为什么没有报错呢,因为a用的是参数里面的a,并不是公有变量中a。 所以,第12行的打印结果,其实打印的是局部变量,也就是说,在构造函数里面我们定义了一套与公有变量同名的变量,在这种情况下,局部变量优先。 所以,self其实非常有作用,必须通过self来显示指定公有变量,不然会当作局部变量。 我们还可以进一步说明这个问题 

进一步证明 

 

结论 

Python类中公有变量和私有变量定义一般定义在类名下面,构造函数上面,比如这样: class A: 公有变量 私有变量 def init(): 。。。 其中私有变量需要有前缀下划线__ 如果成员函数(包括构造函数),中出现了与公有变量(私有变量)同名的变量,则python系统会屏蔽公有变量和私有变量,把改变量当成局部变量。如果要在成员函数(包括构造函数)使用公有变量和私有变量,必须通过self显示指定,就像这样: class A: a = 100 _b = 200 __c = 300 def init(self,a,b,c): self.a = a #使用公有变量a _b = b #屏蔽了公有变量_b,重新定义了一个局部变量_b self.__c =c #使用私有变量__c