python—面向对象设计

Posted zhouyuan666

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python—面向对象设计相关的知识,希望对你有一定的参考价值。

一:三大编程范式

1.面向过程编程
2.函数式编程
3.面向对象编程

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

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

 

 二:类与对象

(在python2中,分新式类经典类,python3统一都是新式类【经典类,class 类名:】【经典类,class 类名(object)】)

技术分享图片
class Chinese:   #class是关键字,表示类名
    pass
print(Chinese)

p1=Chinese() #实例化过程,创建对象,类名后面加括号
print(p1)
小实例

      实例化,由类产生对象的过程叫做实例化,类实例化的结果就是一个对象,或者叫做一个实例   

      ps:类中的函数第一个参数必须是self  类中定义的函数叫做 “方法”

技术分享图片
类是用来描述一类事物,类的对象指的是这一类事物中的一个个体
是事物就要有属性,属性分为:
1.数据属性:就是变量
2.函数属性:就是函数,在面向对象里通常称为方法
注:类和对象均是用点来访问自己的属性
属性
技术分享图片
类是用来描述一类事物,类的对象指的是这一类事物中的一个个体
是事物就要有属性,属性分为:
1.数据属性:就是变量
2.函数属性:就是函数,在面向对象里通常称为方法
注:类和对象均是用点来访问自己的属性
属性
 1 class Chinese:
 2     dang=我爱中国
 3     def tu_tan():
 4         print(张口就是一痰)
 5     def queue(self):
 6         print(随意就是一插)
 7 print(Chinese.dang) #调用类Chinese的数据属性
 8 Chinese.tu_tan() #调用方法
 9 Chinese.queue(zy) #queue方法必须传一个参数
10 print(Chinese.__dict__)  #Chinese所有的方法
11 print(Chinese.__dict__[dang])  #在字典中找出了dang这个数据属性
12 print(Chinese.__dict__[tu_tan]) #内存地址,加()就是地址的内容
13 Chinese.__dict__[tu_tan]()
14 Chinese.__dict__[queue](666) #必须给queue传一个参数
15 
16 # 我爱中国
17 # 张口就是一痰
18 # 随意就是一插
19 # {‘__dict__‘: <attribute ‘__dict__‘ of ‘Chinese‘ objects>, ‘__module__‘: ‘__main__‘, ‘queue‘: <function Chinese.queue at 0x0000029230A14C80>, ‘tu_tan‘: <function Chinese.tu_tan at 0x0000029230A148C8>, ‘dang‘: ‘我爱中国‘, ‘__doc__‘: None, ‘__weakref__‘: <attribute ‘__weakref__‘ of ‘Chinese‘ objects>}
20 # 我爱中国
21 # <function Chinese.tu_tan at 0x0000029230A148C8>
22 # 张口就是一痰
23 # 随意就是一插

 

 对象

 1 class Chinese:
 2     dang=我爱中国
 3     # def __init__(name,age,gender):  #开头结尾都有两个_ _表示是系统内置的方法
 4     #     dic={
 5     #         ‘name‘:name,
 6     #         ‘age‘:age,
 7     #         ‘gender‘:gender
 8     #     }
 9     #     return dic
10     def __init__(self,name,age,gender):
11         print(开始)
12         self.mingzi=name  # 其实就是字典中封装了名字,年级,性别
13         self.nianji=age
14         self.xingbie=gender
15         print(结束)
16 #class的__init__就是不需要返回任何值,它会自动返回
17     def tu_tan():
18         print(张口就是一痰)
19     def queue(self):
20         print(随意就是一插)
21 
22 person1=Chinese(zy,18,female)  #实例化就是在触发系统内置的__init__
23 print(person1.__dict__)  #实例化后的字典形式 __dict__
24 print(person1.mingzi)  #调用person1字典的mingzi
25 print(person1.dang)  #person1调用类class的属性
26 
27 Chinese.tu_tan()
28 Chinese.queue(person1)  #必须传参数
29 
30 结果:
31 # 开始
32 # 结束
33 # {‘xingbie‘: ‘female‘, ‘nianji‘: 18, ‘mingzi‘: ‘zy‘}
34 # zy
35 # 我爱中国
36 # 张口就是一痰
37 # 随意就是一插

 

 类属性的增删改查:

 1 class Chinese:
 2     country=China
 3     def __init__(self,name):
 4         self.name=name
 5     def play_ball(self,ball):
 6         print("%s 正在打%s" %(self.name,ball))
 7 
 8 print(Chinese.country)  #查看
 9 
10 Chinese.country=Japan
11 print(Chinese.country)   #修改
12 
13 p1=Chinese(alex)
14 print(p1.__dict__)
15 print(p1.country)
16 
17 Chinese.dang=dang #增加
18 print(Chinese.dang)
19 print(p1.dang)
20 
21 del Chinese.dang   #删除
22 del Chinese.country
23 print(Chinese.__dict__)
24 
25 结果:
26 # China
27 # Japan
28 # {‘name‘: ‘alex‘}
29 # Japan
30 # dang
31 # dang
32 # {‘__module__‘: ‘__main__‘, ‘__init__‘: <function Chinese.__init__ at 0x000001FE771948C8>, ‘__weakref__‘: <attribute ‘__weakref__‘ of ‘Chinese‘ objects>, ‘__dict__‘: <attribute ‘__dict__‘ of ‘Chinese‘ objects>, ‘play_ball‘: <function Chinese.play_ball at 0x000001FE77194C80>, ‘__doc__‘: None}

 

实例属性的增删改查:  (实例只有数据属性)

 1 class Chinese:
 2     country=China
 3     def __init__(self,name):
 4         self.name=name
 5     def play_ball(self,ball):
 6         print("%s 正在打%s" %(self.name,ball))
 7 p1=Chinese(alex)
 8 print(p1.__dict__)  #实例属性只有{‘name‘: ‘alex‘}
 9 
10 #查看
11 print(p1.name)
12 print(p1.play_ball)  #这一步实际上是访问类
13 
14 #增加
15 p1.age=18
16 print(p1.__dict__)
17 print(p1.age)
18 
19 #修改
20 p1.age=19
21 print(p1.__dict__)
22 print(p1.age)
23 
24 #删除
25 del p1.age
26 print(p1.__dict__)
27 
28 结果:
29 #{‘name‘: ‘alex‘}
30 # alex
31 # <bound method Chinese.play_ball of <__main__.Chinese object at 0x000002042B47A400>>
32 # {‘age‘: 18, ‘name‘: ‘alex‘}
33 # 18
34 # {‘age‘: 19, ‘name‘: ‘alex‘}
35 # 19
36 # {‘name‘: ‘alex‘}

 

对象与实例属性:

 1 class Chinese:
 2     country=China
 3     def __init__(self,name):
 4         self.name=name
 5     def play_ball(self,ball):
 6         print("%s 正在打%s" %(self.name,ball))
 7 p1=Chinese(alex)
 8 print(p1.country)
 9 p1.country=Japan
10 print(Chinese.country) #类的
11 print(p1.country)  #实例的
12 结果:
13 #China
14 #China
15 #Japan
16 
17 country=China
18 class Chinese:
19 
20     def __init__(self,name):
21         self.name=name
22     def play_ball(self,ball):
23         print("%s 正在打%s" %(self.name,ball))
24 p1=Chinese(alex)
25 print(p1.country)   #报错,因为p1调用country在class里面找,找不到不会出去找
26 
27 country=China
28 class Chinese:
29     country=中国
30     def __init__(self,name):
31         self.name=name
32         print(country)
33 #只是返回一个普通的变量,只有点调用的时候才在类属性或者实例属性字典里面去找,所以返回China
34 p1=Chinese(alex)
35 print(p1.country) #这才是调用实例属性,country才是‘中国‘
 1 class Chinese:
 2     country = China
 3     def __init__(self,name):
 4         self.name=name
 5 p1=Chinese(alex)
 6 p1.country=Japan
 7 print(Chinese.country)  #类属性没有变,所以结果还是China
 8 
 9 
10 class Chinese:
11     country = China
12     li=[a,b]
13     def __init__(self,name):
14         self.name=name
15 p1=Chinese(alex)
16 print(p1.li)
17 # p1.li=[666]
18 # print(Chinese.li)  #类的列表还是没变的
19 p1.li.append(cc)   #直接改了类里面的列表
20 print(p1.__dict__)
21 print(Chinese.li)  #类里面的列表被改变之后,打印出来的里边当然是新列表[‘a‘, ‘b‘, ‘cc‘]

 

静态属性:

 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     @property  #在类的普通方法上应用@property装饰器
 9     def cal_area(self):
10         print("%s住的%s总面积是%s" % (self.owner, self.name, self.width * self.heigh * self.length))
11 r1=Room(豪宅,zy,1000,1000,1000)
12 r2=Room(别墅,zt,1000,1200,1300)
13 r1.cal_area
14 r2.cal_area
15 
16 结果:
17 zy住的豪宅总面积是1000000000
18 zt住的别墅总面积是1560000000

 

类方法:

 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     @property  
10     def cal_area(self):
11         print("%s住的%s总面积是%s" % (self.owner, self.name, self.width * self.heigh * self.length))
12     def test(self):
13         print(from test,self.name)
14     def tell_info(self):
15         print(self.tag)
16 print(Room.tag)    #类可以调用自己的数据属性
17 r1=Room(wc,alex,10,100,30) #折中方案,必须先实例化,再。。。。
18 Room.tell_info(r1)
19 
20 结果:1  1
21 
22 优化,类方法:
23 class Room:
24     tag=1
25     def __init__(self,name,owner,width,length,heigh):
26         self.name=name
27         self.owner=owner
28         self.width=width
29         self.length=length
30         self.heigh=heigh
31     @property
32     def cal_area(self):
33         print("%s住的%s总面积是%s" % (self.owner, self.name, self.width * self.heigh * self.length))
34     def test(self):
35         print(from test,self.name)
36     @classmethod
37     def tell_info(cls):
38         print(cls)
39         print(--->,cls.tag)
40 Room.tell_info()  #用类调用类方法,自动传值,把Room传给了tell_info
41 
42 结果:
43 #<class ‘__main__.Room‘>
44 #---> 1

 

静态方法:

1 静态方法只是类的工具包
2 class Room:
3     tag=1
4     @staticmethod
5     def wash_body(a,b,c):
6         print(%s,%s,%s正在洗澡 %(a,b,c))
7 Room.wash_body(zy,zt,zc)
8 结果:zy,zt,zc正在洗澡

 

三:组合(类与类之间没有共同点,但是有关联,拼接类使之间能完成某项功能)

 1 #组合
 2 class School:
 3     def __init__(self,name,addr):
 4         self.name=name
 5         self.addr=addr
 6     def zhao_sheng(self):
 7         print(%s正在招生 %self.name)
 8 class Course:
 9     def __init__(self,name,price,period,school):
10         self.name=name
11         self.price=price
12         self.period=period
13         self.school=school
14 
15 s1=School(oldboy,beijin)
16 s2=School(oldboy,nanjin)
17 s3=School(oldboy,dongjin)
18 
19 c1=Course(linux,10,1h,s1)
20 
21 print(c1.__dict__)
22 print(c1.school.name)
23 
24 结果:
25 #{‘price‘: ‘10‘, ‘school‘: <__main__.School object at 0x00000229CB1EA898>, ‘name‘: ‘linux‘, ‘period‘: ‘1h‘}
26 #oldboy
改进,自己传值:
class School:
    def __init__(self,name,addr):
        self.name=name
        self.addr=addr
    def zhao_sheng(self):
        print(%s正在招生 %self.name)
class Course:
    def __init__(self,name,price,period,school):
        self.name=name
        self.price=price
        self.period=period
        self.school=school

s1=School(oldboy,beijin)
s2=School(oldboy,nanjin)
s3=School(oldboy,dongjin)

# c1=Course(‘linux‘,‘10‘,‘1h‘,s1)
message=‘‘‘
1 oldboy beijin
2 oldboy nanjin
3 oldboy dongjin
‘‘‘
while True:
    print(message)
    menu={
        1:s1,
        2:s2,
        3:s3
    }
    choice=input(选择学校:)
    school_obj=menu[choice]

    name=input(课程名:)
    price=input(课程费用:)
    period=input(课程周期:)

    new_course=Course(name,price,period,school_obj)
    print(课程%s属于%s学校 %(new_course.name,new_course.school.name))

结果:
#1 oldboy beijin
#2 oldboy nanjin
#3 oldboy dongjin

#选择学校:2
#课程名:linux
#课程费用:100
#课程周期:1h
#课程linux属于oldboy学校

 

四:面向对象编程三大特性

     【1】继承(分:单继承,多继承)

 1 class Dad:
 2     money=10000
 3     def __init__(self,name):
 4         print(baba)
 5         self.name=name
 6     def hit_son(self):
 7         print(%s 正在打儿子 %self.name)
 8 
 9 class Son(Dad):
10     pass
11 
12 s1=Son(zy)
13 print(s1.money)
14 print(s1.__dict__)
15 
16 结果:
17 #baba
18 #10000
19 #{‘name‘: ‘zy‘}
技术分享图片
1.当类之间有显著不同,且较小的类是较大类所需的组件时,用组合比较好。
2.当类之间有很多相同的功能,提取这些共同的功能做成基类,用继承比较好。
什么时候用组合,什么时候用继承
技术分享图片
含义一:继承基类的方法,并且做出自己的改变或者扩展(代码重用)
含义二:声明某个子类兼容于某个基类,定义一个接口类,子类继承接口类,并且实现接口中定义的方法。
继承的两种含义
技术分享图片
接口继承
接口继承实际上是要求“做出一个良好的抽象,这个抽象规定了一个兼容接口,使得外部调用者无须关心具体细节,可一视同仁的处理实现了特定接口的所有对象”——这个在程序设计上叫做归一化。(归一化使得高层的外部使用者可以不加区分的处理所有的接口兼容的对象集合)
归一化

继承顺序:深度优先广度优先

(当时经典类时,多继承情况下,会按照深度优先的方法查找。当时新式类时,会按照广度优先的方式查找。)

 

在子类中如何调用父类的方法:

(子类继承父类的方法,然后想基于原有的基础上进行修改,那么就需要在子类中调用父类的方法。)

 1 class Vehicle:
 2     Country=china
 3     def __init__(self,name,speed,load,power):
 4         self.name=name
 5         self.speed=speed
 6         self.load=load
 7         self.power=power
 8     def run(self):
 9         print(开动了)
10 class Subway(Vehicle):
11     def __init__(self,name,speed,load,power,line):
12         Vehicle.__init__(self,name,speed,load,power)
13         self.line = line  #子类中派生出的新的方法
14     def show_info(self):
15         print(self.name,self.speed,self.load,self.power,self.line)
16 line13=Subway(北京地铁,10km/s,10000,,13)
17 line13.show_info()
18 line13.run()
19 
20 结果:
21 #北京地铁 10km/s 10000 电 13
22 #开动了

super调用父类方法:

技术分享图片
 1 class Vehicle:
 2     Country=china
 3     def __init__(self,name,speed,load,power):
 4         self.name=name
 5         self.speed=speed
 6         self.load=load
 7         self.power=power
 8     def run(self):
 9         print(开动了)
10 class Subway(Vehicle):
11     def __init__(self,name,speed,load,power,line):
12         # Vehicle.__init__(self,name,speed,load,power)
13         super().__init__(name,speed,load,power)  #不用写父类了,用super调到父类的方法
14         self.line = line  #子类中派生出的新的方法
15     def show_info(self):
16         print(self.name,self.speed,self.load,self.power,self.line)
17 line13=Subway(北京地铁,10km/s,10000,,13)
18 line13.show_info()
19 line13.run()
20 
21 结果:
22 北京地铁 10km/s 10000 电 13
23 开动了
super()方法

 

  【2】多态(多态的概念指出了对象如何通过他们共同的属性和动作来操作及访问,而不需要考虑他们具体的类。执行过程中才显示出多态。)

  【3】封装()

 1 class People:
 2     _star=earth  #被隐藏起来的,外部不能用,语言约定
 3     def __init__(self,id,name,age,salary):
 4         self.id=id
 5         self.name=name
 6         self_age=age
 7         self._salary=salary
 8     def get_id(self):
 9         print(这是私有方法,它的id是【%s】 %self.id)
10 p1=People(216513548,zy,18,100000000)
11 print(p1._star)

 

以上是关于python—面向对象设计的主要内容,如果未能解决你的问题,请参考以下文章

python面向对象:什么是面向对象程序设计

Python面向对象基础

python ==》 面向对象

Python学习(十三)—— 面向对象程序设计

python之路之前没搞明白4面向对象(封装)

python之面向对象