我们这里就直奔主题,不做基础铺垫,默认你有一些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是私有变量,在类外不能访问

我们程序这样改动

python3 类公共变量 python public变量_python私有变量

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

python3 类公共变量 python public变量_python构造函数_02

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

我们把第8行改造一下:

去掉括号,就像这样:

python3 类公共变量 python public变量_python3 类公共变量_03

a = A会成功生成对象a,而且通过对象a可以正确访问到公有变量a,_b,d。但是在调用函数print_c()的时候,出问题,错误提示

TypeError: print_c() missing 1 required positional argument: ‘self’

提示缺少参数,怎么解决这个问题呢:

显示传递一个类,或者对象进去

python3 类公共变量 python public变量_python构造函数_04


那么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__)

运行结果:

python3 类公共变量 python public变量_python3 类公共变量_05


当我们通过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)          #通过传值构造对象

运行结果:

python3 类公共变量 python public变量_python私有变量_06


这个例子,就证明了构造函数的作用

python中 self的作用

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

python3 类公共变量 python public变量_python构造函数_07

照样可以运行

甚至一个地方用self,一个地方用you也可以

python3 类公共变量 python public变量_python私有变量_08

self的实际意义

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

比如我们去掉self

python3 类公共变量 python public变量_python公有变量_09

运行起来,好像也没问题,但是这里的a,_b,__c,d(构造函数里面),并不是公有变量中的a,_b,__c,d。怎么见得呢?

我们把第七行打开

python3 类公共变量 python public变量_python公有变量_10


运行结果出错:

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来显示指定公有变量,不然会当作局部变量。
我们还可以进一步说明这个问题

进一步证明

python3 类公共变量 python public变量_python私有变量_11

结论

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