Python之面向对象思想

首先在将面向对象之前,我们先来看一个例子:假设我们是一个上帝,现在我们要来生产一条狗,我们假设狗有两个动作:叫还有看门,狗有三个属性:名字、性别、品种,下面我们就来模拟这一条狗,由于狗的动作是固定的,所以我们可以把动作写成方法。
 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 ##   一条博美正在看门
我们很容易就发现问题了
1 people1 = {
2     'name':'小明',
3     'gender':'',
4     'type':''
5 }
6 kanmen(people1)
7 #  一条人正在看门
人怎么能调用狗的动作的,显然是不可以的,所以我们需要把狗的属性和动作捆绑在一起,只有具有狗的属性才能调用狗的动作
 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)
狗的动作和属性
下面我们还可以优化一下
 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就是生成了实实在在的一个狗,也就是对象,所以面向对象包含了两大部分:类和对象。其中类就是一个种类,包含动作和属性。对象就是实例出来的一个具体的例子,只要符合这两点那就是一个面向对象设计。

上面就是一个面向对象设计的例子了,下面我们来用面向对象编程来实现下面的例子:
 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、知道了类的字典属性之后,我们可以对类的数据属性和函数属性进行增删改查:

 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、同样,我们对实例(对象)属性进行增删改查

 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就是对类的数据属性进行操作,和上面的例子有本质上的区别。

猜你喜欢

转载自www.cnblogs.com/maoxinjueluo/p/12612785.html