Python/Article/PythonBasis/python8/5.md

172 lines
4.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# 五、类和对象 #
## 1、类和对象之间的关系 ##
这部分内容主要讲类和对象,我们先来说说类和对象之间的关系。
**类是对象的模板**
我们得先有了类,才能制作出对象。
类就相对于工厂里面的模具,对象就是根据模具制造出来的产品。
**从模具变成产品的过程,我们就称为类的实例化。**
**类实例化之后,就变成对象了。也就是相当于例子中的产品。**
## 2、类的实例化 ##
这里强调一下,类的实例化和直接使用类的格式是不一样的。
之前我们就学过,直接使用类格式是这样的:
```python
class ClassA():
var1 = '两点水'
@classmethod
def fun1(cls):
print('var1 值为:' + cls.var1)
ClassA.fun1()
```
而类的实例化是怎样的呢?
是这样的,可以仔细对比一下,类的实例化和直接使用类的格式有什么不同?
![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-09-025401.png)
主要的不同点有:
* 类方法里面没有了 `@classmethod` 声明了,不用声明他是类方法
* 类方法里面的参数 `cls` 改为 `self`
* 类的使用,变成了先通过 `实例名 = 类()` 的方式实例化对象,为类创建一个实例,然后再使用 `实例名.函数()` 的方式调用对应的方法 ,使用 `实例名.变量名` 的方法调用类的属性
这里说明一下,类方法的参数为什么 `cls` 改为 `self`
其实这并不是说一定要写这个,你改为什么字母,什么名字都可以。
不妨试一下:
![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-09-032030.png)
你看,把 `self` 改为 `aaaaaaaa` 还是可以一样运行的。
只不过使用 `cls``self` 是我们的编程习惯,这也是我们的编程规范。
因为 cls 是 class 的缩写,代表这类 而 self 代表这对象的意思。
所以啊,这里我们实例化对象的时候,就使用 self 。
**而且 self 是所有类方法位于首位、默认的特殊参数。**
除此之外,在这里,还要强调一个概念,当你把类实例化之后,里面的属性和方法,就不叫类属性和类方法了,改为叫实例属性和实例方法,也可以叫对象属性和对象方法。
为什么要这样强调呢?
**因为一个类是可以创造出多个实例对象出来的。**
你看下面的例子:
![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-09-034453.png)
我不仅能用这个类创建 a 对象,还能创建 b 对象
## 3、实例属性和类属性 ##
一个类可以实例化多个对象出来。
![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-09-040408.png)
根据这个图,我们探究一下实例对象的属性和类属性之间有什么关系呢?
**先提出第一个问题,如果类属性改变了,实例属性会不会跟着改变呢?**
还是跟以前一样,提出了问题,我们直接用程序来验证就好。
看程序:
![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-09-061015.png)
从程序运行的结果来看,**类属性改变了,实例属性会跟着改变。**
这很好理解,因为我们的实例对象就是根据类来复制出来的,类属性改变了,实例对象的属性也会跟着改变。
**那么相反,如果实例属性改变了,类属性会改变吗?**
答案当然是不能啦。因为每个实例都是单独的个体,不能影响到类的。
具体我们做下实验:
![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-09-062437.png)
可以看到,**不管实例对象怎么修改属性值,对类的属性还是没有影响的。**
## 4、实例方法和类方法 ##
那这里跟上面一样,还是提出同样的问题。
**如果类方法改变了,实例方法会不会跟着改变呢?**
看下下面的例子:
![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-09-063242.png)
这里建议我的例子,各位都要仔细看一下,自己重新敲一遍。相信为什么要这么做,这么证明。
还是那句话多想,多敲。
回归正题,从运行的结果来看,类方法改变了,实例方法也是会跟着改变的。
在这个例子中,我们需要改变类方法,就用到了**类的重写**。
我们使用了 `类.原始函数 = 新函数` 就完了类的重写了。
要注意的是,这里的赋值是在替换方法,并不是调用函数。所以是不能加上括号的,也就是 `类.原始函数() = 新函数()` 这个写法是不对的。
**那么如果实例方法改变了,类方法会改变吗?**
如果这个问题我们需要验证的话,是不是要重写实例的方法,然后观察结果,看看类方法有没有改变,这样就能得出结果了。
可是我们是不能重写实例方法。
你看,会直接报错。
![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-09-064303.png)