Python之面向对象思想
本节掌握两个知识点:
一、什么叫面向对象
二、类的属性和对象的属性
首先在了解面向对象之前,我们先来看一个例子:假设我们是一个上帝,现在我们要来生产一条狗,我们假设狗有两个动作:叫还有看门,狗有三个属性:名字、性别、品种,下面我们就来模拟这一条狗,由于狗的动作是固定的,所以我们可以把动作写成方法。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 og1 = { 2 'name':'旺财', 3 'gender':'母', 4 'type':'哈士奇' 5 } 6 dog2 = { 7 'name':'小狗', 8 'gender':'公', 9 'type':'博美' 10 } 11 def jiao(dog): 12 print('一条%s正在叫'%dog['name']) 13 def kanmen(dog): 14 print('一条%s正在看门'%dog['type']) 15 jiao(dog1) 16 kanmen(dog2) 17 ## 一条旺财正在叫 18 ## 一条博美正在看门
我们很容易就发现问题了
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 people1 = { 2 'name':'小明', 3 'gender':'男', 4 'type':'人' 5 } 6 kanmen(people1) 7 # 一条人正在看门
人怎么能调用狗的动作的,显然是不可以的,所以我们需要把狗的属性和动作捆绑在一起,只有具有狗的属性才能调用狗的动作
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 def dog(name,gender,type): 2 def jiao(dog): 3 print('一条%s正在叫' % dog['name']) 4 5 def kanmen(dog): 6 print('一条%s正在看门' % dog['type']) 7 8 dog1 = { 9 'name': name, 10 'gender': gender, 11 'type': type, 12 'jiao':jiao, 13 'kanmen':kanmen 14 } 15 return dog1 16 17 d1 = dog('旺财','母','哈士奇') 18 d2 = dog('小狗','公','博美') 19 print(d1) 20 print(d2) 21 d1['jiao'](d1)
下面我们还可以优化一下
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 def dog(name,gender,type): 2 def init(name,gender,type): ## 定义了狗的属性和动作,实际上就是初始化一只狗 3 dog1 = { 4 'name': name, 5 'gender': gender, 6 'type': type, 7 'jiao':jiao, 8 'kanmen':kanmen 9 } 10 return dog1 11 12 def jiao(dog): ## 狗的动作 13 print('一条%s正在叫' % dog['name']) 14 15 def kanmen(dog): ## 狗的动作 16 print('一条%s正在看门' % dog['type']) 17 18 return init(name,gender,type) 19 d1 = dog('旺财','母','哈士奇') 20 d2 = dog('小狗','公','博美') 21 print(d1) 22 print(d2)
这样看起来代码就整洁多了,其中init()就是初始化一只狗,事实上上面就是一个面向对象设计了。我们来观察上面的例子,上面的dog()函数定义了动作与特征,也就是定义了狗这一个种类,而d1就是生成了实实在在的一个狗,也就是对象,所以面向对象包含了两大部分:类和对象。其中类就是一个种类,包含动作和属性。对象就是实例出来的一个具体的例子,只要符合这两点那就是一个面向对象设计。
上面就是一个面向对象设计的例子了,下面我们来用面向对象编程来实现下面的例子:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 class Dog: 2 def __init__(self,name,gender,type): ## 这个就是上面的init() 函数,初始化函数,类一运行就会执行这个函数 3 self.name = name 4 self.gender = gender 5 self.type = type 6 7 def jiao(self): ## 这里的self实际上就是对象本身 8 print('一条%s正在叫'%self.name) 9 10 def kanmen(self): 11 print('一条%s正在看门'%self.type) 12 13 d1 = Dog('旺财','母','哈士奇') 14 d2 = Dog('小狗','公','博美') 15 d1.jiao() 16 d2.kanmen() 17 #一条旺财正在叫 18 # 一条博美正在看门
下面我们来总结一下:
1、面向对象分为两种:面向对象设计和面向对象编程,只要包含一类事物的总和(类 )以及这一类产生了实例,那就是一个面向对象。所以并不是包含class(类)才叫做面向对象。
2、面向对象两个概念:类(class)和对象(object)。其中类就是一类事物的特征和动作的总和(例如人这一个种类),是一个抽象的概念。
而对象就是由这一个类实例化出来的一个具体的例子,就好比是一个个的人。
3、什么叫实例化:由类产生对象这一个过程就叫实例化,结果是一个对象或者叫一个实例。
- 类的相关知识:
类有两个属性:数据属性和函数属性
1、下面我们来看一下类的数据属性和函数属性
1 class Chinese: 2 color = 'yellow' ## 数据属性 3 def quality(): ## 函数属性 4 print('中国人有着勤劳勇敢的品德') 5 6 def sell(self): ## 函数属性 7 print('中国人爱经商') 8 9 ## 下面我们来打印Chinese这一类的数据属性和函数属性(方法属性) 10 11 print(Chinese.color) ## yellow 12 print(Chinese.quality) ## <function Chinese.quality at 0x000000000262E2F0> 13 print(Chinese.sell) ## <function Chinese.sell at 0x000000000262E378> 14 15 ## 我们来运行类的函数 16 Chinese.quality() ## 中国人有着勤劳勇敢的品德 17 Chinese.sell(123) ## 中国人有着勤劳勇敢的品德
类有一个方法:__dict__,调用这个方法可以打印出类的所有属性,返回的是一个字典的形式,下面我们把类的属性打印出来
print(Chinese.__dict__) ## {'__module__': '__main__', 'color': 'yellow', 'quality': <function Chinese.quality at 0x000000000216E2F0>, 'sell': <function Chinese.sell at 0x000000000216E378>, '__dict__': <attribute '__dict__' of 'Chinese' objects>, '__weakref__': <attribute '__weakref__' of 'Chinese' objects>, '__doc__': None} ## 我们把这个属性字典里的数据属性以及函数属性打印出来 print(Chinese.__dict__['color']) ## yellow print(Chinese.__dict__['quality']) ## <function Chinese.quality at 0x000000000283E2F0> print(Chinese.__dict__['sell']) ## <function Chinese.sell at 0x000000000283E378> ## 我们把这个属性字典里的函数打印出来 Chinese.__dict__['quality']() ## 中国人有着勤劳勇敢的品德 Chinese.__dict__['sell'](123) ## 中国人爱经商
实际上上面打印的 Chinese.color 这个数据属性就是从 __dict__ 这里面的属性字典里面取出来的。
2、知道了类的字典属性之后,我们可以对类的数据属性和函数属性进行增删改查:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 class Chinese: 2 color = 'yellow' 3 def __init__(self,name,age,gender): ## 这里self 这个参数就是对象本身,实例化对象第一步就是运行 __init__() 这个函数 4 self.name = name 5 self.age = age 6 self.gender = gender 7 8 def quality(): 9 print('中国人有着勤劳勇敢的品德') 10 11 def sell(self): 12 print('中国人爱经商') 13 14 p1 = Chinese('alex',18,'男') 15 ## 数据属性 增 16 Chinese.Country = '中国' 17 print(Chinese.__dict__['Country']) ## 中国 18 19 ## 删 20 del Chinese.Country 21 22 ## 改 23 Chinese.color = '白色' 24 print(Chinese.__dict__['color']) ## 白色 25 26 ## 函数属性 增 27 def sport(self): 28 print("中国人%s喜欢打乒乓球"%self.name) 29 Chinese.sport = sport 30 p1.sport() ## 中国人alex喜欢打乒乓球 31 32 ## 改 (其实就是重新写一个函数,去覆盖原来的函数) 33 def sell(self): 34 print('中国人%s爱占小便宜'%self.name) 35 Chinese.sell = sell 36 p1.sell() ## 中国人alex爱占小便宜
- 对象的相关知识
1、我们首先来看一下对象有什么属性
1 class Chinese: 2 color = 'yellow' 3 def __init__(self,name,age,gender): ## 这里self 这个参数就是对象本身,实例化对象第一步就是运行 __init__() 这个函数 4 self.name = name 5 self.age = age 6 self.gender = gender 7 8 def quality(): 9 print('中国人有着勤劳勇敢的品德') 10 11 def sell(self): 12 print('中国人爱经商') 13 14 p1 = Chinese('alex',18,'man') 15 print(p1.__dict__) ## {'name': 'alex', 'age': 18, 'gender': 'man'}
可以看出来, p1 这个对象只有数据属性,那我们看一下能不能调用类的函数属性呢?
1 print(p1.color) ## yellow 这里想一下:为什么明明p1 的字典属性里没有color这个数据属性,为什么这里能打印出来呢? 2 p1.sell() ## 中国人爱经商 3 p1.quality() 4 ## 报错: Traceback (most recent call last): 5 # File "F:/PycharmProjects/复习/面向对象/面向对象思想.py", line 152, in <module> 6 # p1.quality() 7 # TypeError: quality() takes 0 positional arguments but 1 was given
这里提出两个问题:
(1)、为什么 p1 能够调用字典属性里面没有的数据属性和函数属性呢?
(2)、为什么 p1 调用 quality()函数会报错呢?
实际上这个就是作用域的原因,首先 p1 会在自己的字典属性里面找,如果找不到就会去类的字典属性里去找,我们可以看到类的字典属性里是有上面的数据属性和函数属性的,如果还找不到就会报错了。
至于第二个问题,是因为对象在调用方法属性时,底层会自动把对象作为一个参数传入函数中,由于quality()里并没有接收这个参数,所以就报错了。
2、同样,我们对实例(对象)属性进行增删改查
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 class Chinese: 2 color = 'yellow' 3 def __init__(self,name,age,gender): 4 self.name = name 5 self.age = age 6 self.gender = gender 7 8 def quality(): 9 print('中国人有着勤劳勇敢的品德') 10 11 def sell(self): 12 print('中国人爱经商') 13 14 p1 = Chinese('alex',18,'男') 15 print(p1.__dict__) ## {'name': 'alex', 'age': 18, 'gender': '男'} 16 ## 改 17 p1.name = '武则天' 18 print(p1.__dict__) ## {'name': '武则天', 'age': 18, 'gender': '男'} 19 ## 增 20 p1.money = 1000000 21 print(p1.__dict__) ## {'name': '武则天', 'age': 18, 'gender': '男', 'money': 1000000} 22 ## 删 23 del p1.money 24 print(p1.__dict__) ## {'name': '武则天', 'age': 18, 'gender': '男'}
补充:下面我们对类和对象的属性进行操作
观察一下:
1 class Chinese: 2 color = 'yellow' 3 def __init__(self,name,age,gender): 4 self.name = name 5 self.age = age 6 self.gender = gender 7 8 def quality(): 9 print('中国人有着勤劳勇敢的品德') 10 11 def sell(self): 12 print('中国人爱经商') 13 14 p1 = Chinese('alex',18,'男') 15 p1.color = '白色的' 16 print(Chinese.color) ## yellow
想一下: 为什么我们通过 对象 修改了color这个类的数据属性时,类的数据属性并没有修改呢?
我们打印一下对象的数据属性
print(p1.__dict__) ## {'name': 'alex', 'age': 18, 'gender': '男', 'color': '白色的'}
可以看出,实际上我们是在给对象属性增加了color这个元素,和类的color这个数据属性没有任何关系,只不过名字一样而已。
那么下面继续看另一个操作:
1 class Chinese: 2 color = 'yellow' 3 l = ['a','b'] 4 def __init__(self,name,age,gender): 5 self.name = name 6 self.age = age 7 self.gender = gender 8 9 def quality(): 10 print('中国人有着勤劳勇敢的品德') 11 12 def sell(self): 13 print('中国人爱经商') 14 15 p1 = Chinese('alex',18,'男') 16 p1.l.append('c') 17 print(Chinese.l) ## ['a', 'b', 'c']
为什么这里类的属性被修改了呢?
同样,我们打印一下对象的数据属性:
print(p1.__dict__) ## {'name': 'alex', 'age': 18, 'gender': '男'}
我们这里可以看出来,对象的数据属性并没有任何变化。事实上,这里append就是对类的数据属性进行操作,和上面的例子有本质上的区别。