1
Python之权限控制
权限控制
在Python中,实例的变量名如果以双下划线”__”开头,它就变成了一个私有变量,类似于C++当中的private属性,只有内部可以访问,外部不能访问,假设我们这样定义一个Student类:
这里我们在属性的名称前面都加了双下划綫,如果此时,我们直接调用name属性,就会发生报错,如下图所示:
我们定义了一个student对象,叫做‘ZhaoLiu’,可以发现,我们无论如何访问,都不能通过stu这个的对象访问到它的属性__name,但是当我们调用它的方法print_score时,我们可以得到如下的结果:
也就是说,print_score可以访问属性__score,如果此时我们必须要得到name和score这两个属性,但是又不想改变类的定义,可以采用如下办法:我们定义两个新函数get_name和get_score,让这两个函数去返回我们想要的两个变量。还可以通过设定一个set_score函数去更改score的值,这样虽然看着比较绕,不如直接修改score直观,但是可以通过限定条件避免一些非法的输入。
双下划线开头的实例变量是不是一定不能从外部访问呢?其实也不是。不能直接访问__name是因为Python解释器对外把__name变量改成了_Student__name,所以,仍然可以通过_Student__name来访问__name变量:
但是强烈建议你不要这么干,因为不同版本的Python解释器可能会把__name改成不同的变量名
2
一个小坑
一个小坑
下面看看这个例子:
我们可以发现,虽然我们把名字yangguo的“__name属性”改成了“XiaoLongNv”,但是当我们调用get_name()的时候,真正的name属性还是‘yangguo’,表面上看,外部代码“成功”地设置了__name变量,但实际上这个__name变量和class内部的__name变量不是一个变量!内部的__name变量已经被Python解释器自动改成了_Student__name,而外部代码给bart新增了一个__name变量。
3
继承和多态
继承和多态
继承和多态这部分和C++很像,如果你对C++很了解,那看着肯定很轻松。先说继承,顾名思义,当我们定义一个class的时候,可以从别的class继承,新的类成为继承类的子类,而被继承的类称为基类或者父类。这里我们举个例子来说明一下:
我们首先写个Animal的类,它里面包含了一个run的方法,再从Animal中继承出来Cat和Dog类,语法是在类定义的括号中将object替换成Animal。Cat和Dog中分别有两种方法,一个是run,一个是eat,下面我们进行实验:
我们发现Dog和Cat都调用了它们自己的run方法,也就是‘Dog is running’和‘Cat is running’,这个时候,我们再重新写一个tiger的类,也继承自Animal,不同的是tiger没有run方法,只有一个eat方法,结果如下:
这里我们总结一下:
1.当子类和父类都有run方法的时候,子类的run方法将父类的run方法覆盖了,代码运行的时候调用的是子类的run方法;
2.当子类中没有run方法而父类中存在run方法时,子类将调用父类的run方法;
3.当子类中有eat方法而父类中没有eat方法时,子类将调用自己的eat方法;
这就是Python当中的继承和多态,当我们新增一种Animal的子类时,子类可以直接调用父类的方法,当子类定义了和父类同名的方法时,子类的方法将覆盖父类方法。此时,若新建一个父类的子类时,只需要定义子类需要的方法而不用管父类原来的代码是如何调用的。这就是著名的“开闭”原则:
1.对扩展开放:允许新增子类
2.对修改封闭:不需要修改父类的函数
继承还可以一层一层的继承下来,最终产生一棵继承树,如下:
最后我们使用isinstance来看看dog的数据类型:
我们可以看到,dog对象既是一个Dog对象也是一个Animal对象
4
实例属性和类属性
我们前面所说的内容都是给一个对象添加某个属性,如果我们需要给一个类添加一个属性应该怎么做?来看下面这个例子:
这个例子可以分为4部分,第一部分是类定义,给一个类定义一个属性name,在第二部分我们可以发现类的对象也可以调用它的属性,第三部分是当我们改变对象的属性时,类自身的属性不发生变化,第四部分是当我们删除对象的属性时,该对象属性重新指向类的属性。
从上面的例子可以看出,在编写程序的时候,千万不要对实例属性和类属性使用相同的名字,因为相同名称的实例属性将屏蔽掉类属性,但是当你删除实例属性后,再使用相同的名称,访问到的将是类属性。