代码改变世界

Python--面向对象编程

2017-01-04 22:19  ZN23&24  阅读(89)  评论(0)    收藏  举报

python基础-面向对象编程

一、三大编程范式                                                                                                                                     

编程范式即编程的方法论,标识一种编程风格


三大编程范式:

1.面向过程编程

2.函数式编程

3.面向对象编程

二、编程进化论                                                                                                                                        

1.编程最开始就是无组织无结构,从简单控制流中按步写指令

2.从上述的指令中提取重复的代码块或逻辑,组织到一起(比方说,你定义了一个函数),便实现了代码重用,且代码由无结构走向了结构化,创建程序的过程变得更具逻辑性

3.我们定义函数都是独立于函数外定义变量,然后作为参数传递给函数,这意味着:数据与动作是分离的

4.如果我们把数据和动作内嵌到一个结构(函数或类)里面,那么我们就有了一个‘对象系统’(对象就是数据与函数整合到一起的产物)。

复制代码
1 假设你是一条狗,我们用结构化的数据来描述你
2 1:数据与动作分离
3 2:数据与动作结合
4 
5 导向:
6 1.面向对象设计
7 2.什么是类什么是对象
复制代码

三、面向对象设计与面向对象编程                                                                                                                

def定义函数是面向对象

class定义类是面向对象

 

1、面向对象设计

面向对象设计(Object oriented design):将一类具体事物的数据和动作整合到一起,即面向对象设计

示例1:

复制代码
 1 #相当于:类
 2 def dog(name,gender,type):
 3     #狗的动作
 4     def jiao(dog):
 5         print('一条狗[%s],汪汪汪' % dog['name'])
 6     def chi_shi(dog):
 7         print('一条[%s] 正在吃肉' % dog['type'])
 8     #狗的属性
 9     def init(name,gender,type):
10         dog1 = {
11             'name':name,
12             'gender':gender,
13             'type':type,
14             'jiao':jiao,    #动作
15             'chi_shi':chi_shi,   #动作
16         }
17         return dog1
18     return init(name,gender,type)
19 
20 d1=dog('元吴','母','中华犬')
21 d2=dog('alex','母','藏敖')
22 print(d1)
23 print(d2)
24 d1['jiao'](d1)
25 d2['chi_shi'](d2)
复制代码

什么是类?

类:把一类事物的相同的特征和动作整合到一起就是类,类是一个抽象的概念。

什么是对象?

对象:就是基于类而创建的一个具体的事物(指具体存在的),也是特征和动作整合到一起。

 

示例2:

学校类:
特征:name,addr,type
动作:考试,招生,开除学生

复制代码
 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-      
 3 #Author: nulige
 4 
 5 def school(name,addr,type):
 6     def init(name, addr, type):
 7         sch = {
 8             'name': name,
 9             'addr': addr,
10             'type': type,
11             'kao_shi': kao_shi,
12             'zhao_sheng': zhao_sheng,
13         }
14         return sch
15     def kao_shi(school):
16         print('%s 学校正在考试' %school['name'])
17     def zhao_sheng(school):
18         print('%s %s 正在招生' %(school['type'],school['name']))
19     return  init(name,addr,type)
20 
21 s1=school('oldboy','沙河','私立学校')
22 print(s1)
23 print(s1['name'])
24 
25 s1['zhao_sheng'](s1)
26 
27 s2=school('清华','北京','公立学校')
28 
29 print(s2)
30 print(s2['name'],s2['addr'],s2['type'])
31 s2['zhao_sheng'](s2)
复制代码

 

2、面向对象编程

面向对象编程(object-oriented programming):用定义类+实例/对象的方式去实现面向对象的设计

复制代码
 1 #用面向对象编程独有的语法class去实现面向对象设计
 2 class Dog:
 3     def __init__(self,name,gender,type):   #实例化的过程,就是运行__init__
 4         self.name=name
 5         self.gender=gender
 6         self.type=type
 7 
 8     def bark(self):
 9         print('一条名字为[%s]的[%s],狂吠不止' %(self.name,self.type))
10 
11     def yao_ren(self):
12         print('[%s]正在咬人' %(self.name))
13 
14     def chi_shi(self):
15         print('[%s]正在吃屎' %(self.type))
16 
17 dog1=Dog('alex','female','京巴')
18 dog2=Dog('wupeiqi','female','腊肠')
19 dog3=Dog('yuanhao','female','藏獒')
20 
21 dog1.bark()
22 dog2.yao_ren()
23 dog3.chi_shi()
复制代码

小结:

  在Python中,类和 OOP 都不是日常编程所必需的。尽管它从一开始设计就是面向对象的,并且结构上支持 OOP,但 Python 没有限定或要求你在你的应用中写 OOP 的代码。

用面向对象语言写程序和一个程序的设计是面向对象的,两者就是两码事

 

四、类和对象                                                                                                                                          

1.什么叫类:类是一种数据结构,就好比一个模型,该模型用来表述一类事物(事物即数据和动作的结合体),用它来生产真实的物体(实例)。

2.什么叫对象:睁开眼,你看到的一切的事物都是一个个的对象,你可以把对象理解为一个具体的事物(事物即数据和动作的结合体)

(铅笔是对象,人是对象,房子是对象,狗是对象,alex是对象,配齐是对象,元昊是对象)

3.类与对象的关系:对象都是由类产生的,上帝造人,上帝首先有一个造人的模板,这个模板即人的类,然后上帝根据类的定义来生产一个个的人

4.什么叫实例化:由类生产对象的过程叫实例化,类实例化的结果就是一个对象,或者叫做一个实例(实例=对象)

 

五、类的相关知识                                                                                                                                   

1、初识类

在python中声明函数与声明类很相似。

 

声明函数

1
2
3
1 def functionName(args):
2      '函数文档字符串'
3       函数体

 

声明类

复制代码
 1 '''
 2 class 类名:
 3     '类的文档字符串'
 4     类体
 5 '''
 6 
 7 #我们创建一个类
 8 class Data:
 9     pass
10 
11 #用类Data实例化出一个对象d1
12 d1=Data()
复制代码

 

经典类与新式类

复制代码
 1 大前提:
 2 1.只有在python2中才分新式类和经典类,python3中统一都是新式类
 3 2.新式类和经典类声明的最大不同在于,所有新式类必须继承至少一个父类
 4 3.所有类甭管是否显式声明父类,都有一个默认继承object父类(讲继承时会讲,先记住)
 5 在python2中的区分
 6 经典类:
 7 class 类名:
 8     pass
 9 
10 经典类:
11 class 类名(父类):
12     pass
13 
14 在python3中,上述两种定义方式全都是新式类
复制代码

 示例:

复制代码
 1 #经典类(python2.7)
 2 class Chinese:
 3     '这是一个中国人的类'
 4     pass
 5 
 6 print(Chinese)
 7 
 8 #新式类(python3.0)
 9 
10 #实例化到底干了什么?
11 p1=Chinese() #实例化
12 print(p1)
复制代码

 

2、属性

类是用来描述一类事物,类的对象指的是这一类事物中的一个个体

是事物就要有属性,属性分为

1:数据属性:就是变量

2:函数属性:就是函数,在面向对象里通常称为方法

注意:类和对象均用点来访问自己的属性

 

类的属性

理论:数据属性即变量,类的定义与函数又极其类似,其实可以用函数的作用域来理解类的属性调用。

 

类的数据属性

复制代码
1 #定义一个中文人的类,然后在类中定义一个类的属性,政府是共产堂,这样,只要是中文人他们的党永远都是共产堂
2 #类属性又称为静态变量,或者是静态数据。这些数据是与它们所属的类对象绑定的,不依赖于任何类实例。
3 #如果你是一位Java或C++程序员,这种类型的数据相当于在一个变量声明前加上static关键字。
4 
5 class Chinese:
6     government='共产堂'
7 
8 print(Chinese.government)
复制代码

 

类的函数属性(又称为方法)

复制代码
 1 class Chinese:
 2     government='***'
 3     def sui_di_tu_tan():
 4         print('90%的中国人都喜欢随地吐痰')
 5 
 6     def cha_dui(self):
 7         print('一个中国人-->%s<--插到了前面' %self)
 8 
 9 Chinese.sui_di_tu_tan()
10 
11 person1_obj='alex'
12 Chinese.cha_dui(person1_obj) #带参函数,所以调用时需要传入参数,将'alex'传给self
复制代码

 

查看类属性

我们定义的类的属性到底存到哪里了?有两种方式查看
dir(类名):查出的是一个名字列表

类名.__dict__:查出的是一个字典,key为属性名,value为属性值

复制代码
 1 #共有属性,动作(方法)
 2 class Chinese:
 3     '这是一个中国人的类'
 4     dang='共产堂'             #数据属性
 5     def sui_di_tu_tan():     #函数属性
 6         print('朝着墙上就是一口痰')
 7     def cha_dui(self):       #加了self的就必须传一个参数,否则会报错
 8         print('插到了前面')
 9 
10 print(Chinese.dang)
11 Chinese.sui_di_tu_tan()
12 Chinese.cha_dui('元昊')
13 
14 # print(dir(Chinese))            #查看系统内置属性
15 # print(Chinese.__dict__)        #查看属性字典
16 print(Chinese.__dict__['dang'])  #调用数据属性,本身就是在数据属性中找东西
17 Chinese.__dict__['sui_di_tu_tan']()  #调用函数属性,有了函数的内存地址,加(),就可以运行
18 Chinese.__dict__['cha_dui'](1)       #调用函数属性
复制代码

执行结果:

复制代码
1 共产堂
2 在地上就是一口痰
3 插到了前面
4 共产堂
5 在地上就是一口痰
6 插到了前面
复制代码

 

特殊的类属性

复制代码
 1 class Chinese:
 2     '我们都是中国人,我们骄傲的活着,我们不服任何事和物'
 3     government='共产堂'
 4     def sui_di_tu_tan():
 5         print('90%的中国人都喜欢随地吐痰')
 6 
 7     def cha_dui(self):
 8         print('一个中国人-->%s<--插到了前面' %self)
 9 
10 print(Chinese.__name__)  #类C的名字(字符串)
11 print(Chinese.__doc__)   #类C的文档字符串
12 print(Chinese.__base__)  #类C的第一个父类(在讲继承时会讲)
13 print(Chinese.__bases__) #类C的所有父类构成的元组(在讲继承时会讲)
14 print(Chinese.__dict__)  #类C的属性
15 print(Chinese.__module__)#类C定义所在的模块
16 print(Chinese.__class__) #实例C对应的类(仅新式类中)
复制代码

 

六、对象相关知识                                                                                                                                   

  对象是由类实例化而来,类实例化的结果称为一个实例或者称作一个对象

1.1、实例化

  什么是实例化?

  由类生产对象的过程就叫实例化

复制代码
 1 class Chinese:
 2     '我们都是中国人,我们骄傲的活着,我们不服任何事和物'
 3     government='***'
 4     def sui_di_tu_tan():
 5         print('90%的中国人都喜欢随地吐痰')
 6 
 7     def cha_dui(self):
 8         print('一个中国人-->%s<--插到了前面' %self)
 9 
10 person1=Chinese() #类名加上括号就是实例化(可以理解为函数的运行,返回值就是一个实例)
11 
12 #这就是实例化,只不过你得到的person1实例,没有做任何事情
复制代码

 

1.2、构造函数

类是数据属性和函数属性的结合,描述的是一类事物

这类事物的一个具体表现就是一个实例/对象,比方说中国人是一个类,而你就是这个类的一个实例

你除了有中国人这个数据属性外,还应该有名字,年龄,性别等数据属性

如何为实例定制数据属性,可以使用类的一个内置方法__init__()该方法,在类()实例化是会自动执行

复制代码
 1 class Chinese:
 2     '我们都是中国人,我们骄傲的活着,我们不服任何事和物'
 3     government='***'
 4     def __init__(self,name,age,gender): #实例化的过程可以简单理解为执行该函数的过程,实例本身会当作参数传递给self(这是默认的步骤)
 5         self.name=name
 6         self.age=age
 7         self.gender=gender
 8 
 9     def sui_di_tu_tan():
10         print('90%的中国人都喜欢随地吐痰')
11 
12     def cha_dui(self):
13         print('一个中国人-->%s<--插到了前面' %self)
14 
15 # person1=Chinese() #会报错
16                         #自动执行__init__方法,而这个方法需要参数,
17                         # 这些参数应该写在类名后面的括号里,然后由类传
18                         #给__init__函数,也就说,传给类的参数就是传给__init__的参数
19 
20 person1=Chinese('alex',1000,'female')
21 person2=Chinese('wupeiqi',10000,'female')
22 person3=Chinese('yuanhao',9000,'female')
23 
24 print(person1.__dict__)
复制代码

注意:在说实例化的时候说过,执行类()会自动返回一值,这个值就是实例,而类()会自动执行__init__,所以一定不要在该函数内定义返回值,会冲突。

 

1.3、实例属性

理论:

1.实例只有数据属性(实例的函数属性严格来说是类的函数属性)

2.del 实例/对象,只是回收了实例的数据属性,函数属性是属于类的,是不会回收。

实例化的过程实际就是执行__init__的过程,这个函数内部只是为实例本身即self设定了一堆数据(变量),所以实例只有数据属性。

复制代码
 1 class Chinese:
 2     '我们都是中国人,我们骄傲的活着,我们不服任何事和物'
 3     government='***'
 4     def __init__(self,name,age,gender):
 5         self.name=name
 6         self.age=age
 7         self.gender=gender
 8 
 9     def sui_di_tu_tan():
10         print('90%的中国人都喜欢随地吐痰')
11 
12     def cha_dui(self):
13         print('一个中国人-->%s<--插到了前面' %self)
14 
15 
16 person1=Chinese('alex',1000,'female')
17 print(person1.__dict__) #查看实例的属性,发现里面确实只有数据属性
18 print(person1.name,person1.age,person1.gender) #访问实例的数据属性
复制代码

那么我们想访问实例的函数属性(其实是类的函数属性),如何实现

复制代码
 1 class Chinese:
 2     '我们都是中国人,我们骄傲的活着,我们不服任何事和物'
 3     government='***'
 4     def __init__(self,name,age,gender):
 5         self.name=name
 6         self.age=age
 7         self.gender=gender
 8 
 9     def sui_di_tu_tan():
10         print('90%的中国人都喜欢随地吐痰')
11 
12     def cha_dui(self):
13         print('一个中国人-->%s<--插到了前面' %self)
14 
15 
16 person1=Chinese('alex',1000,'female')
17 print(person1.__dict__) #查看实例的属性,发现里面确实只有数据属性
18 print(Chinese.__dict__)#函数属性只存在于类中
19 Chinese.cha_dui(person1)#我们只能通过类去调用类的函数属性,然后把实例当做变量传递给self
复制代码

改进版本

复制代码
 1 class Chinese:
 2     '我们都是中国人,我们骄傲的活着,我们不服任何事和物'
 3     government='***'
 4     def __init__(self,name,age,gender):
 5         self.name=name
 6         self.age=age
 7         self.gender=gender
 8 
 9     def sui_di_tu_tan():
10         print('90%的中国人都喜欢随地吐痰')
11 
12     # def cha_dui(self):
13     #     print('一个中国人-->%s<--插到了前面' %self)
14 
15     def cha_dui(self):
16         print('一个中国人-->姓名:%s 年龄:%s 性别:%s<--插到了前面' %(self.name,self.age,self.gender))
17 
18     def eat_food(self,food):
19         print('%s 正在吃 %s' %(self.name,food))
20 
21 person1=Chinese('alex',1000,'female')
22 print(person1.__dict__) #查看实例的属性,发现里面确实只有数据属性
23 print(Chinese.__dict__)#函数属性只存在于类中
24 Chinese.cha_dui(person1)#我们只能通过类去调用类的函数属性,然后把实例当做变量传递给self
25 Chinese.eat_food(person1,'韭菜馅饼')
26 
27 
28 person1.cha_dui()#其实就是Chinese.cha_dui(person1)
29 person1.eat_food('飞禽走兽') #本质就是Chinese.eat_food(person1,'飞禽走兽')
复制代码

 

3、实例属性和查看实例属性的方法如下:

同样是dir和内置__dict__两种方式

 

                                                            原理图

示例:

复制代码
 1 class Chinese:
 2     '这是一个中国人的类'
 3 
 4     dang='共产堂'
 5 
 6     def __init__(self,name,age,gender):
 7         print('我是初始化函数,我开始运行了')
 8         self.mingz=name     #name,age,gender都封装在self里面
 9         self.nianji=age     #p1.nianji=age
10         self.xingbin=gender #p1.xingbin=gender
11         print('我结束啦')
12 
13     def sui_di_tu_tan():
14         print('在地上就是一口痰')
15     def cha_dui(self):
16         print(self)
17         print('%s 插到了前面' %self)
18     #return None (系统默认就是return None,这里不要加return)
19 
20 #数据属性
21 p1=Chinese('元昊','18','female')   #实例化的过程,就是调用__init__
22 print(p1.__dict__)       #查看字典属性  #==>{'nianji': '18', 'mingz': '元昊', 'xingbin': 'female'}
23 print(p1.mingz)          #p1.nianji=age, 直接调用__init__里面的属性,
24 print(p1.dang)           #类的作用域概念,如果__init__里面没有,就去外面那层找,外层找到Class Chinese类字典
25 
26 #实例属性没有函数属性,函数属性属于类
27 print(Chinese.__dict__)
28 Chinese.sui_di_tu_tan()
29 Chinese.cha_dui(p1)
30 
31 #p1.sui_di_tu_tan()  #class把p1作为参数自动加到sui_di_tu_tan(p1)括号里面,所以会报错。因为是python底层自动加上的。
32 p1.cha_dui()         #p1里面没有,但是类里面有,所以能找到
复制代码

执行结果:

复制代码
 1 我是初始化函数,我开始运行了
 2 我结束啦
 3 {'mingz': '元昊', 'xingbin': 'female', 'nianji': '18'}
 4 元昊
 5 共产堂
 6 {'__init__': <function Chinese.__init__ at 0x0121F0C0>, '__doc__': '这是一个中国人的类', '__module__': '__main__', '__weakref__': <attribute '__weakref__' of 'Chinese' objects>, 'sui_di_tu_tan': <function Chinese.sui_di_tu_tan at 0x0121F270>, 'dang': '共产堂', 'cha_dui': <function Chinese.cha_dui at 0x0121F228>, '__dict__': <attribute '__dict__' of 'Chinese' objects>}
 7 在地上就是一口痰
 8 <__main__.Chinese object at 0x01681210>
 9 <__main__.Chinese object at 0x01681210> 插到了前面
10 <__main__.Chinese object at 0x01681210>
11 <__main__.Chinese object at 0x01681210> 插到了前面
12 China
13 Japan
14 {'name': 'alex'}
15 {'__init__': <function Chinese.__init__ at 0x0121F108>, 'dang': '共产堂', '__module__': '__main__', 'play_ball': <function Chinese.play_ball at 0x0121F198>, '__weakref__': <attribute '__weakref__' of 'Chinese' objects>, 'country': 'Japan', '__doc__': None, '__dict__': <attribute '__dict__' of 'Chinese' objects>}
16 共产堂
17 {'__init__': <function Chinese.__init__ at 0x0121F108>, '__module__': '__main__', 'play_ball': <function Chinese.play_ball at 0x0121F198>, '__weakref__': <attribute '__weakref__' of 'Chinese' objects>, '__doc__': None, '__dict__': <attribute '__dict__' of 'Chinese' objects>}
18 {'__init__': <function Chinese.__init__ at 0x0121F108>, '__module__': '__main__', 'play_ball': <function Chinese.play_ball at 0x0121F198>, '__weakref__': <attribute '__weakref__' of 'Chinese' objects>, '__doc__': None, 'eat': <function eat_food at 0x011F2F60>, '__dict__': <attribute '__dict__' of 'Chinese' objects>}
19 alex 正在吃虾
20 test
复制代码

 

1.4、特殊实例属性

__class__

__dict__

复制代码
 1 class Chinese:
 2     '我们都是中国人,我们骄傲的活着,我们不服任何事和物'
 3     government='***'
 4     def __init__(self,name,age,gender):
 5         self.name=name
 6         self.age=age
 7         self.gender=gender
 8 
 9     def sui_di_tu_tan():
10         print('90%的中国人都喜欢随地吐痰')
11 
12     # def cha_dui(self):
13     #     print('一个中国人-->%s<--插到了前面' %self)
14 
15     def cha_dui(self):
16         print('一个中国人-->姓名:%s 年龄:%s 性别:%s<--插到了前面' %(self.name,self.age,self.gender))
17 
18     def eat_food(self,food):
19         print('%s 正在吃 %s' %(self.name,food))
20 
21 person1=Chinese('alex',1000,'female')
22 
23 print(person1.__class__)
24 print(Chinese)
25 
26 person2=person1.__class__('xiaobai',900,'male')
27 print(person2.name,person2.age,person2.gender)
复制代码

警告:类和对象虽然调用__dict__返回的是一个字典结构,但是千万不要直接修改该字典,会导致你的oop不稳定。

 

1.5、类属性与对象(实例)属性

1、类属性的增、删、改、查 

复制代码
 1 class Chinese:
 2     country='China'
 3     def __init__(self,name):
 4         self.name=name
 5 
 6     def play_ball(self,ball):
 7         print('%s 正在打 %s' %(self.name))
 8 
 9 #查看
10 print(Chinese.country)
11 
12 #修改
13 Chinese.country='Japan'
14 print(Chinese.country)
15 
16 p1=Chinese('alex')
17 print(p1.__dict__)   #从类的字典里面去找,上面已经修改过了,所以是Japan
18 
19 #增加
20 Chinese.dang='共产堂'
21 
22 #printChinese.dang)
23 #print(p1.dang)
24 
25 #删除
26 del Chinese.dang
27 del Chinese.country
28 
29 print(Chinese.__dict__)
30 #print(Chinese.country)
31 
32 
33 #给类增加一个函数属性
34 def eat_food(self,food):   #定义了一个函数,
35     print('%s 正在吃%s' %(self.name,food))
36 
37 Chinese.eat=eat_food
38 
39 print(Chinese.__dict__)
40 p1.eat('虾')    #给函数属性传参数
41 
42 
43 #增加
44 def test(self):
45     print('test')
46 
47 Chinese.play_ball=test
48 p1.play_ball()  #Chinese.play_ball(p1)
复制代码

执行结果:

复制代码
 1 China
 2 
 3 Japan
 4 
 5 {'name': 'alex'}
 6 
 7 {'play_ball': <function Chinese.play_ball at 0x01558108>, '__init__': <function Chinese.__init__ at 0x01085660>, '__doc__': None, '__weakref__': <attribute '__weakref__' of 'Chinese' objects>, '__module__': '__main__', '__dict__': <attribute '__dict__' of 'Chinese' objects>}
 8 
 9 {'play_ball': <function Chinese.play_ball at 0x01558108>, '__init__': <function Chinese.__init__ at 0x01085660>, '__doc__': None, 'eat': <function eat_food at 0x01532F60>, '__weakref__': <attribute '__weakref__' of 'Chinese' objects>, '__module__': '__main__', '__dict__': <attribute '__dict__' of 'Chinese' objects>}
10 
11 alex 正在吃虾
12 
13 test
复制代码

 

2、实例属性的增、删、改、查 

复制代码
 1 class Chinese:
 2     country='China'
 3     def __init__(self,name):
 4         self.name=name
 5 
 6     def play_ball(self,ball):
 7         print('%s 正在打 %s' %(self.name,ball))
 8 p1=Chinese('alex')
 9 print(p1.__dict__)
10 
11 #查看
12 # print(p1.name)
13 # print(p1.play_ball)
14 
15 #增加
16 p1.age=18
17 print(p1.__dict__)
18 print(p1.age)
19 
20 #不要修改底层的属性字典
21 # p1.__dict__['sex']='male'
22 # print(p1.__dict__)
23 # print(p1.sex)
24 
25 #修改
26 p1.age=19
27 print(p1.__dict__)
28 print(p1.age)
29 
30 #删除
31 del p1.age
32 print(p1.__dict__)
复制代码

执行结果:

复制代码
1 {'name': 'alex'}
2 
3 {'age': 18, 'name': 'alex'}
4 18
5 
6 {'age': 19, 'name': 'alex'}
7 19
8 
9 {'name': 'alex'}
复制代码

 

1.其实你会发现,实例化就是 类名(),然后返回的结果是一个对象,加上括号是不是跟函数运行很像,函数运行完了有返回值,是不是很像,没错,就是一样的。

2.函数又作用域的概念,其实类也有作用域的概念,二者一样

3.你可以把class当做最外层的函数,是一个作用域

复制代码
 1 #定义一个类,只当一个作用域去用,类似于c语言中的结构体
 2 class MyData:
 3     pass
 4 
 5 x=10
 6 y=20
 7 MyData.x=1
 8 MyData.y=2
 9 
10 print(x,y)
11 print(MyData.x,MyData.y)
12 print(MyData.x+MyData.y)
复制代码

4.实例化会自动触发init函数的运行,最后返回一个值即实例,我们要找的实例属性就存放在init函数的局部作用域里

5.类有类的属性字典,就是类的作用域,实例有实例的属性字典,即实例的作用域

6.综上,一个点代表一层作用域,obj.x先从自己的作用域找,自己找不到去外层的类的字典中找,都找不到,就会报错

7.在类中没有使用点的调用,代表调用全局变量。

 

上面知识应用:

示例1:

复制代码
 1 class Chinese:
 2     country='China'
 3     def __init__(self,name):
 4         self.name=name
 5 
 6     def play_ball(self,ball):
 7         print('%s 正在打 %s' %(self.name,ball))
 8 
 9 p1=Chinese('alex')
10 print(p1.country)                 #访问的是类的
11 p1.country='日本'                  #把country改成日本
12 print('类的--->',Chinese.country)  #类的---> China
13 print('实例的',p1.country)         #在类的字典里,新增了一个p1.country='日本'。所以发果是:实例的 日本
复制代码

 

示例2:

复制代码
 1 country='中国'
 2 class Chinese:
 3     def __init__(self,name):
 4         self.name=name
 5 
 6     def play_ball(self,ball):
 7         print('%s 正在打 %s' %(self.name,ball))
 8 
 9 p1=Chinese('alex')
10 # print(p1.country)   #p1.country就是在类里面找,找不到就报错。
复制代码

 

示例3:

复制代码
 1 country='中国'
 2 class Chinese:
 3     def __init__(self,name):
 4         self.name=name
 5 
 6     def play_ball(self,ball):
 7         print('%s 正在打 %s' %(self.name,ball))
 8 
 9 #另外定义一个函数,接收输入
10 def shi_li_hua():
11     name=input('>>: ')
12     p1=Chinese(name)
13     # print(p1.country)
14     print(p1.name)
15 shi_li_hua()
复制代码

 

示例4:

复制代码
 1 country='中华人民共和国'
 2 class Chinese:
 3     country='中国'
 4 
 5     def __init__(self,name):
 6         self.name=name
 7         print('--->',country)  #即不是类的属性,也不是实例的属性。所以他就是变量的直接赋值
 8 
 9     def play_ball(self,ball):
10         print('%s 正在打 %s' %(self.name,ball))
11 
12 p1=Chinese('alex')             #打印出来的值是变量, ---> 中华人民共和国
复制代码

 

示例5:

复制代码
 1 country='中国'        #从外面去找
 2 class Chinese:
 3     country='中国'
 4     def __init__(self,name):
 5         self.name=name
 6         print('--->',country)  #即不是类的属性,也不是实例的属性。所以他就是变量
 7 
 8     def play_ball(self,ball):
 9         print('%s 正在打 %s' %(self.name,ball))
10 
11 #调用实例数据属性的两种方法如下:
12 
13 #用.的方式调用:
14 print(Chinese.__dict__)
15 print(Chinese.country)
16 
17 结果:
18 ---> 中国
19 
20 #通过实例调用
21 p1=Chinese('alex')
22 print('实例--------》',p1.country)
23 
24 结果:
25 实例--------》 中国
复制代码

总结:

.的方式调用的是属性,要么跟类有关,要么跟实例有关

不加.就跟类没关,跟实例没关。

 

示例1:

复制代码
 1 class Chinese:
 2     country='China'
 3     def __init__(self,name):
 4         self.name=name
 5 
 6     def play_ball(self,ball):
 7         print('%s 正在打 %s' %(self.name,ball))
 8 p1=Chinese('alex')
 9 
10 print(p1.country)    #打印的就是country本身
11 p1.country='Japan'   #增加了一个实例,类本身不会更改
12 print(Chinese.country)
复制代码

 

示例2:

复制代码
 1 class Chinese:
 2     country='China'
 3     l=['a','b']
 4     def __init__(self,name):
 5         self.name=name
 6 
 7     def play_ball(self,ball):
 8         print('%s 正在打 %s' %(self.name,ball))
 9 
10 p1=Chinese('alex')
11 print(p1.l)        #p1本身自己没有,找的就是类,所以打印出来的值就是:['a', 'b']
12 
13 p1.l=[1,2,3]
14 print(Chinese.l)   #l 的值不会变,因为他是在1里面加入了一个新的字典。结果:['a', 'b']
15 print(p1.__dict__) #因为他是在1里面加入了一个新的字典。结果:{'l': [1, 2, 3], 'name': 'alex'}
复制代码

 

示例3:

复制代码
 1 class Chinese:
 2     country='China'
 3     l=['a','b']
 4     def __init__(self,name):
 5         self.name=name
 6 
 7     def play_ball(self,ball):
 8         print('%s 正在打 %s' %(self.name,ball))
 9 
10 p1=Chinese('alex')
11 print(p1.l)          #p1本身自己没有,找的就是类,所以打印出来的值就是:['a', 'b']
12 
13 p1.l.append('c')     #这不是在赋值和给实例新增属性。执行结果:['a', 'b']
14 print(p1.__dict__)   #执行结果:{'name': 'alex'}
15 print(Chinese.l)     #改的就是类里面的东西,所以直接增加进去了。执行结果:['a', 'b', 'c']
复制代码

理论 :类的作用域即函数作用域

 

七、静态属性、类方法、静态方法                                                                                                                          

1、静态属性  

作用就是:封装逻辑,把函数属性封装成数据属性

复制代码
 1 class Room:
 2     def __init__(self,name,owner,width,length,heigh):
 3         self.name=name
 4         self.owner=owner
 5         self.width=width
 6         self.length=length
 7         self.heigh=heigh
 8 
 9     @property     #静态属性
10     def cal_area(self):     #计算面积
11         return self.width * self.length
12 
13     @property
14     def cal_volume(self):    #计算体积
15         return self.width * self.length * self.heigh
16 
17 r1=Room('厕所','alex',1000,100,100000)  
18 r2=Room('公共厕所','yuanhao',1,1,1)
19 r3=Room('主人房','nulige',10,10,10)
20 
21 print(r1.cal_area)
22 print(r2.cal_area)
23 print(r3.cal_volume)
24 print(r1.name)
25 print(r2.name)
26 print(r3.name)
复制代码

执行结果:

复制代码
1 100000
2 1
3 1000
4 厕所
5 公共厕所
6 主人房
复制代码

 

2、类方法

类方法作用:专门给类使用与实例无关,类方法只能访问类相关属性,不能访问实例属性(跟实例没有任何关系)

复制代码
 1 class Room:
 2     tag=1
 3     def __init__(self, name, owner, width, length, heigh):
 4         self.name = name
 5         self.owner = owner
 6         self.width = width
 7         self.length = length
 8         self.heigh = heigh
 9 
10     @property
11     def cal_area(self):
12         return self.width * self.length
13 
14     @classmethod     #classmethod类方法只是给类使用(不管是否存在实例),只能访问实例变量
15 def tell_info(cls,x): 16 print(cls) 17 print('---->',cls.tag) 18 19 Room.tell_info(1)
复制代码

执行结果:

1 <class '__main__.Room'>
2 ----> 1

 

3、静态方法

复制代码
 1 '''
 2 staticmethod静态方法只是名义上的归属类管理,不能使用类变量和实例变量,是类的工具包
 3 '''
 4 
 5 class Room:
 6     def __init__(self,name,owner,width,length):
 7         self.name=name
 8         self.owner=owner
 9         self.width=width
10         self.length=length
11 
12     @property
13     def cal_area(self):
14         return self.width * self.length
15 
16     @staticmethod    #类的工具包,不跟类绑定,也不跟实例绑定(无法调用实例的东西)
17 def wash_body(): 18 print('洗刷刷,洗刷刷') 19 20 def test(): 21 print('这可不是静态方法,用类调用没问题,你用一个实例调用看看') 22 23 Room.wash_body() 24 25 r1=Room('厕所','alex',10,10) 26 r1.wash_body() 27 28 29 30 #------ 31 Room.test() 32 r1.test() #会报错,因为如果test不是静态方法,那么r1会吧自己传给test的第一个参数self,test无参所以报错 33 34 静态方法
复制代码

 

八、组合                                                                                                                                                           

一、组合的组成部分

定义一个人的类,人有头,驱赶,手,脚等数据属性,这几个属性又可以是通过一个类实例化的对象,这就是组合

简单理解:就是大类包含小类,就是组合。

用途:

1:做关联

2:小的组成大的

复制代码
 1 class Hand:
 2     pass
 3 
 4 class Foot:
 5     pass
 6 
 7 class Trunk:
 8     pass
 9 
10 class Head:
11     pass
12 
13 class Person:
14     def __init__(self,id_num,name):
15         self.id_num=id_num  #身份证号码
16         self.name=name
17         self.hand=Hand()
18         self.foot=Foot()
19         self.trunk=Trunk()
20         self.head=Head()
21 
22 p1=Person('111111','alex')  #给实例传值
23 print(p1.__dict__)          #查看实例的属性字典
复制代码

执行结果:

1 {'foot': <__main__.Foot object at 0x011B4130>, 'trunk': <__main__.Trunk object at 0x011B4170>, 'id_num': '111111', 'hand': <__main__.Hand object at 0x011B40D0>, 'name': 'alex', 'head': <__main__.Head object at 0x011B4190>}

 

二、选课系统

示例1:

复制代码
 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-      
 3 #Author: nulige
 4  
 5 #选课系统
 6 
 7 #一种很LOW的关联方法:
 8 class School:
 9     def __init__(self,name,addr):
10         self.name=name
11         self.addr=addr
12         self.course_list=[]
13 
14     def zhao_sheng(self):
15         print('%s 正在招生' %self.name)
16 
17 class Course:
18     def __init__(self,name,price,period):
19         self.name=name
20         self.price=price
21         self.period=period
22 
23 s1=School('oldboy','北京')
24 s2=School('oldboy','上海')
25 s3=School('oldboy','天津')
26 
27 c1=Course('linux',5800,'1h')
28 c2=Course('python',9800,'1h')
29 
30 s1.course_list.append(c1)
31 s1.course_list.append(c2)
32 print(s1.__dict__)    #打印字典属性
33 
34 for course_obj in s1.course_list:
35     print(course_obj.name,course_obj.price)
复制代码

执行结果:

1 {'course_list': [<__main__.Course object at 0x01984190>, <__main__.Course object at 0x019841B0>], 'name': 'oldboy', 'addr': '北京'}
2 
3 linux 5800
4 python 9800

 

示例2:

用组合的方式实现

复制代码
 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-      
 3 #Author: nulige
 4  
 5 class School:
 6     def __init__(self,name,addr):
 7         self.name=name
 8         self.addr=addr
 9 
10     #招生
11     def zhao_sheng(self):
12         print('%s 正在招生' %self.name)
13 
14 class Course:
15     def __init__(self,name,price,period,school):
16         self.name=name
17         self.price=price
18         self.period=period
19         self.school=school
20 
21 s1=School('oldboy','北京')
22 s2=School('oldboy','上海')
23 s3=School('oldboy','天津')
24 
25 # c1=Course('linux',5800,'1h','oldboy北京')
26 # c1=Course('python',9800,'1h',s1 )
27 
28 msg='''
29 1 老男孩 北京校区
30 2 老男孩 上海校区
31 3 老男孩 天津校区
32 '''
33 while True:
34     print(msg)
35     menu={
36         '1':s1,
37         '2':s2,
38         '3':s3,
39     }
40 
41     choice=input('请选择学校:')
42     school_obj=menu[choice]
43     name=input('课程名: ')
44     price=input('课程费用: ')
45     period=input('课程周期: ')
46     new_course=Course(name,price,period,school_obj)
47     print('课程[%s] 属于[%s] 学校' %(new_course.name,new_course.school.name))
复制代码

执行结果:

 1 1 老男孩 北京校区
 2 2 老男孩 上海校区
 3 3 老男孩 天津校区
 4 
 5 请选择学校:1
 6 课程名: python
 7 课程费用: 9800
 8 课程周期: 1h
 9 课程[python] 属于[oldboy] 学校
10 
11 1 老男孩 北京校区
12 2 老男孩 上海校区
13 3 老男孩 天津校区
14 
15 请选择学校: