python基础之面向对象初级篇

本文介绍了面向对象编程的基础知识,对比了面向过程和函数式编程,重点讲解了Python中的面向对象编程,包括类的定义、对象的创建以及封装、继承和多态等核心概念。通过实例展示了如何使用面向对象编程实现功能,使代码更加结构化和易于维护。
摘要由CSDN通过智能技术生成

初级篇

  • 面向过程:根据业务逻辑从上到下写垒代码
  • 函数式:将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可
  • 面向对象:对函数进行分类和封装,让开发“更快更好更强...”

面向对象编程是一种编程方式,此编程方式的落地需要使用 “类” 和 “对象” 来实现,所以,面向对象编程其实就是对 “类” 和 “对象” 的使用,如果使用函数式编程,需要在每次执行函数时传入相同的参数,如果参数多的话,又需要粘贴复制了...  ;而对于面向对象只需要在创建对象时,将所有需要的参数封装到当前对象中,之后再次使用时,通过self间接去当前对象中取值即可。

比如函数式编程

def kanchai(name, age, gender):
    print "%s,%s岁,%s,上山去砍柴" %(name, age, gender)


def qudongbei(name, age, gender):
    print "%s,%s岁,%s,开车去东北" %(name, age, gender)


def dabaojian(name, age, gender):
    print "%s,%s岁,%s,最爱大保健" %(name, age, gender)


kanchai('小明', 10, '男')
qudongbei('小明', 10, '男')
dabaojian('小明', 10, '男')


kanchai('老李', 90, '男')
qudongbei('老李', 90, '男')
dabaojian('老李', 90, '男')

面对对象编程

class Foo:
    
    def __init__(self, name, age ,gender):
        self.name = name
        self.age = age
        self.gender = gender

    def kanchai(self):
        print "%s,%s岁,%s,上山去砍柴" %(self.name, self.age, self.gender)

    def qudongbei(self):
        print "%s,%s岁,%s,开车去东北" %(self.name, self.age, self.gender)

    def dabaojian(self):
        print "%s,%s岁,%s,最爱大保健" %(self.name, self.age, self.gender)


xiaoming = Foo('小明', 10, '男')
xiaoming.kanchai()
xiaoming.qudongbei()
xiaoming.dabaojian()

laoli = Foo('老李', 90, '男')
laoli.kanchai()
laoli.qudongbei()
laoli.dabaojian()

面向对象的思维过程:

# 对象是具体的有其特征和动作,然后从众多的对象中抽象出类来
#举例狗,以一条具体的狗来举例,用字典来描述特征和动作

#思维:首先按过程先特征后动作的来描述具体对象
# dog1={
#     'name':'元昊',
#     'gender':'母',
#     'type':'藏獒'  #基本特征
# }

# 狗的基本动作
# def jiao(dog): #函数中通过输入参数来形成互动
#     print('一条狗[%s],汪汪汪' % dog['name'])
# def chi_shi(dog):
#     print('一条[%s] 正在吃屎' % dog['type'])
# jiao(dog1)
# chi_shi(dog1)
# #缺点:要反复建参数字典而且如果不是狗,比如人只要有参数就可以一样显示

#改进:1,用局部作用域 2 字典里将动作也加进来

# def dog():# 以狗为对象做局部作用域,和特征动作为字典来描述对象
#
#     def jiao (dog):  # 函数中通过输入参数来形成互动
#         print('一条狗[%s],汪汪汪' % dog['name'])
#
#     def chi_shi(dog):
#         print('一条[%s] 正在吃屎' % dog['type'])
#
#     dog1 = {
#         'name': '元昊',
#         'gender': '母',
#         'type': '藏獒',
#         'jiao': jiao,
#         'chi_shi':chi_shi,
#     }
#
#     return dog1
#
# d1 = dog()
# print(d1) #{'name': '元昊', 'gender': '母', 'type': '藏獒', 'jiao': <function dog.<locals>.jiao at 0x0000020743571C80>, 'chi_shi': <function dog.<locals>.chi_shi at 0x0000020743571D08>}
# d1['jiao'](d1) # 一条狗[元昊],汪汪汪
#
# 缺点:因为参数固定,只能有一条狗,所以还要加入形参变成可输入互动

# def dog(name,gender,type):# 以狗为对象做局部作用域,和特征动作为字典来描述对象
#     def init(name, gender, type):  # 通过一个初始化函数定义了狗这类的基本特征和动作
#         dog1 = {
#             'name': name,
#             'gender': gender,
#             'type': type,
#             'jiao': jiao,
#             'chi_shi': chi_shi,
#         }
#         return dog1
#     def jiao (dog):  # 动作用函数描述,函数中通过输入参数来形成互动
#         print('一条狗[%s],汪汪汪' % dog['name'])
#
#     def chi_shi(dog): # 动作用函数描述,函数中通过输入参数来形成互动
#         print('一条[%s] 正在吃屎' % dog['type'])
#
#     return init(name,gender,type)
#
#
# d1 = dog('alex','公','吉娃娃')
# print(d1) #{'name': 'alex', 'gender': '公', 'type': '吉娃娃', 'jiao': <function dog.<locals>.jiao at 0x000001A49E821C80>, 'chi_shi': <function dog.<locals>.chi_shi at 0x000001A49E821D08>}
# print(d1['name']) #alex
# d1['jiao'](d1) #一条狗[alex],汪汪汪

#例二 :学校 特征:name,addr,type 动作:招生,开除,考试
# school1={
#     'name':'old boy',
#     'addr':'沙河',
#     'type':'私立'
# }
#
# def kao_shi(school):
#     print('%s学校正在考试'%school['name'])
# def zhao_sheng(school):
#     print('%s %s 学校正在招生'%(school['type'],school['name']))
#
# kao_shi(school1) #old boy学校正在考试
# zhao_sheng(school1)#私立 old boy 学校正在招生

#改进:通过对学校作为对象来设立函数加入作用域、设立形参、特征动作的联动
# def school(name,addr,type):
#
#
#     def kao_shi(sch):
#         print('%s学校正在考试'%sch['name'])
#     def zhao_sheng(sch):
#         print('%s %s 学校正在招生'%(sch['type'],sch['name']))
#
#     sch = {
#         'name': name,
#         'addr': addr,
#         'type': type,
#         'kao_shi': kao_shi,
#         'zhao_sheng': zhao_sheng
#     }
#     return sch
#
# s1 = school('old boy','沙河','私立')
# print(s1) #{'name': 'old boy', 'addr': '沙河', 'type': '私立', 'kao_shi': <function school.<locals>.kao_shi at 0x000001D24F791C80>, 'zhao_sheng': <function school.<locals>.zhao_sheng at 0x000001D24F791D08>}
# s1['kao_shi'](s1) #old boy学校正在考试

#改进:通过def init函数,这样通过完全的几个函数将对象上升到对某类别的编程,对象:某一学校 上升到:类别:学校
# def school(name,addr,type):
#     def init(name, addr, type):
#         sch = {
#             'name': name,
#             'addr': addr,
#             'type': type,
#             'kao_shi': kao_shi,
#             'zhao_sheng': zhao_sheng
#         }
#         return sch
#     def kao_shi(sch):
#         print('%s学校正在考试'%sch['name'])
#     def zhao_sheng(sch):
#         print('%s %s 学校正在招生'%(sch['type'],sch['name']))
#     return init(name,addr,type)
#
# s1 = school('old boy','沙河','私立')
# print(s1) #{'name': 'old boy', 'addr': '沙河', 'type': '私立', 'kao_shi': <function school.<locals>.kao_shi at 0x000001D24F791C80>, 'zhao_sheng': <function school.<locals>.zhao_sheng at 0x000001D24F791D08>}
# s1['kao_shi'](s1)

类和实例对象:

  • class是关键字,表示类
  • 创建对象,类名称后加括号即可
# class Chinese:
#     '这是一个中国人的类'
#     pass
#
# #实例化到底干了什么?
# p1=Chinese() #实例化
# print(p1) #<__main__.Chinese object at 0x00000264B79D0978>
'''
1.数据属性
2.函数属性
'''
# print(Chinese.__name__) # Chinese 类的名称
# print(Chinese.__doc__) #这是一个中国人的类 类的文档
# print(Chinese.__bases__) #<class 'object'>
# print(Chinese.__module__)#__main__此模块在本文件中
# print(Chinese.__class__) # <class 'type'>

# class Chinese:
#     '这是一个中国人的类'
#
#     dang='共产党'

    # def __init__(name,age,gender):
    #     dic={
    #         'name':name,
    #         'age':age,
    #         'gender':gender
    #     }
    #     return dic
#     def __init__(self,name,age,gender): # 必须要有self参数,表示实例自己,而且不能有return
#         print('我是初始化函数,我开始运行了')
#         self.mingzi=name  #p1.mingzi=name
#         self.nianji=age   #p1.nianji=age
#         self.xingbie=gender
#         print('我结束啦')
#     def sui_di_tu_tan(self):
#         print('%s 朝着墙上就是一口痰' %self.mingzi)
#     def cha_dui(self):
#         print(self)
#         print('%s 插到了前面' %self.mingzi)
#     def eat_food(self,food):
#         print('%s 正在吃%s' %(self.mingzi,food))
#
# p1 = Chinese('元昊', 18, 'female')# 实例化,相当于调用了函数  我是初始化函数,我开始运行了 我结束啦
# print(p1) #<__main__.Chinese object at 0x0000021EF69643C8>
# print(p1.__dict__)#{'mingzi': '元昊', 'nianji': 18, 'xingbie': 'female'} 就是实例本身,某个具体的对象,但只包含数据属性,没有函数属性
# print((p1.__dict__)['nianji']) #18
# print(p1.nianji) #18
# print(p1.dang)#共产党
# Chinese.sui_di_tu_tan(p1) #元昊 朝着墙上就是一口痰
# p1.sui_di_tu_tan() #元昊 朝着墙上就是一口痰 虽然未输入参数,但实际是默认把p1传入了,如果非要传入p1,会报错多传了
# p1.eat_food('鱼')

 基本属性操作:

# class Chinese:
#     country='China'
#     def __init__(self,name):
#         self.name=name
#
#     def play_ball(self,ball):
#         print('%s 正在打 %s' %(self.name,ball))
# #查看
# print(Chinese.country) #China
#
# #修改
# Chinese.country='Japan'
# print(Chinese.country) #Japan
#
# p1=Chinese('alex')
# print(p1.__dict__) #{'name': 'alex'}
# print(p1.country) #Japan
#
# #增加
# Chinese.dang='共产党'
#
# print(Chinese.dang) #共产党
# print(p1.dang)#共产党
#
# #删除
# del Chinese.dang
# del Chinese.country
#
# print(Chinese.__dict__)
#print(Chinese.country) #删除后,再查询就报错了AttributeError: type object 'Chinese' has no attribute 'country'

#
# def eat_food(self,food):#目前新写的要追加的函数和类是同级,故写好后要完善下面那句
#     print('%s 正在吃%s' %(self.name,food))
#
# Chinese.eat=eat_food
#
# print(Chinese.__dict__)
# p1.eat('肉')


# def test(self):
#     print('test')

#Chinese.play_ball=test # 将原函数用新的函数名替代掉就名字不变,但函数体里的内容更换过来了
#p1.play_ball()# Chinese.play_ball(p1) test
#p1.test() # 这个运行无结果
#
# p1.age=18 #追加实例的属性
# print(p1.__dict__) # {'name': 'alex', 'age': 18}
# print(p1.age) # 18

# def test(self):
#     print('这是实例的函数属性')
# p1.test = test
# print(p1.__dict__) #'name': 'alex', 'age': 18, 'test': <function test at 0x0000023609F6B158>}
# p1.test(p1) #这是实例的函数属性
#
# p1.age=19 # 修改
# print(p1.__dict__) #{'name': 'alex', 'age': 19, 'test': <function test at 0x0000022EAE28B158>}
# print(p1.age) #19
#
# del p1.test #删除
# print(p1.__dict__) #{'name': 'alex', 'age': 19}

进一步理解类属性和实例属性:

 class Chinese:
#     country='China'
#     l=['a','b']
#     def __init__(self,name):
#         self.name=name
#
#     def play_ball(self,ball):
#         print('%s 正在打 %s' %(self.name,ball))
# p1=Chinese('alex')
# print(p1.l) # ['a', 'b']
# p1.l=[1,2,3] # 修改了实例的属性,但类的属性不变
# print(Chinese.l) #['a', 'b'] 类的属性不变
# print(p1.__dict__)#{'name': 'alex', 'l': [1, 2, 3]}
# p1.l.append('c')# 还是在修改实例属性
# print(p1.__dict__) #{'name': 'alex', 'l': [1, 2, 3, 'c']}
# print(Chinese.l) # ['a', 'b'] 类的属性不变

# p1.l.append('c')# 如果之前没有p1.l=[1,2,3](此命令是给实例增加了一个l的属性) ,就直接运行此命令,那么这在修改类的属性
# print(p1.__dict__) #{'name': 'alex'}实例属性不变
# print(Chinese.l) # ['a', 'b', 'c'] 类的属性变了

 

面向对象的三大特性是指:封装、继承和多态

1 封装 对于面向对象的封装来说,其实就是使用构造方法将内容封装到 对象 中,然后通过对象直接或者self间接获取被封装的内容

class Room:
    def __init__(self,name,owner,width,length,high):
        self.name=name
        self.owner=owner
        self.__width=width #此参数的设定外部不可见,开始准备封装
        self.__length=length
        self.__high=high

    def tell_area(self): #此时我们想求的是面积,给对方开个接口直接见结果,但细节均不可见
        return self.__width * self.__length *self.__high

    def tell_width(self):
        return self.__width


r1=Room('卫生间','alex',100,100,10000)

#arear=r1.__width * r1.__length # 'Room' object has no attribute '__width',因为参数对外不可见
print(r1.tell_area())

2 继承 子可以继承父的内容 对于面向对象的继承来说,其实就是将多个类共有的方法提取到父类中,子类仅需继承父类而不必一一实现每个方法,除了子类和父类的称谓,你可能看到过 派生类 和 基类 ,他们与子类和父类只是叫法不同而已

  • 当类是经典类时,多继承情况下,会按照深度优先方式查找
  • 当类是新式类时,多继承情况下,会按照广度优先方式查找

 

类的组合和继承:

 由类变成组合,原理:各类之间没有共同点,但有关联,所以就把类当成参数输入到另一类中,形成了组合

# 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','北京')
# s2=School('oldboy','南京')
# s3=School('oldboy','东京')
#
# c=Course('linux',10,'1h','oldboy 北京')
# c1=Course('linux',10,'1h',s1)
#
# print(c.__dict__)#{'name': 'linux', 'price': 10, 'period': '1h', 'school': 'oldboy 北京'}
# print(c1.__dict__) #{'name': 'linux', 'price': 10, 'period': '1h', 'school': <__main__.School object at 0x000001E64D354898>}
# print(c1.school.name)# 从组合中调用类的对应的属性,也是用.来表示层级关系 #oldboy
# print(s1)#<__main__.School object at 0x00000217E5B647F0> 表示实例化的对象
# print(s1.__dict__)#{'name': 'oldboy', 'addr': '北京'},实例化的数据属性
# print(s1.zhao_sheng) #<bound method School.zhao_sheng of <__main__.School object at 0x000001F84C8947F0>>
# s1.zhao_sheng() #oldboy 正在招生 实例化后调用类的函数属性


#利用组合+input 构建一套学生自己选课的系统
# 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','北京')
# s2=School('oldboy','南京')
# s3=School('oldboy','东京')
#
# # c1=Course('linux',10,'1h','oldboy 北京')
# # c1=Course('linux',10,'1h',s1)
#
# msg='''
# 1 老男孩 北京校区
# 2 老男孩 南京校区
# 3 老男孩 东京校区
# '''
# while True:
#     print(msg)
#     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)) #课程【linux】属于【oldboy】学校

#类的继承:各类之间有不少的相同之处,可以用类的继承
# class Dad:
#     '这个是爸爸类'
#     money=10
#     def __init__(self,name):
#         print('爸爸')
#         self.name=name
#     def hit_son(self):
#         print('%s 正在打儿子' %self.name)
#
# class Son(Dad): # 类SON需继承父类DAD,所以传入的参数是DAD
#     money = 1000000000009
#     def __init__(self,name,age):
#         self.name=name
#         self.age=age
#
#     def hit_son(self):
#         print('来自儿子类')
#
# print(Son.money) # 10,说明已经继承了父类的数据属性
# # print(Dad.__dict__)
# # print(Son.__dict__)
# s1=Son('alex',18) #按类的继承,参数是父亲的参数
# print(s1.name)#alex
# s1.hit_son()#alex 正在打儿子
#
# #但是如果子类有自己的属性,就会用自己的属性取代掉父亲的属性。


#接口继承,适合归一化设计
# import abc
# class All_file(metaclass=abc.ABCMeta):
#     @abc.abstractmethod
#     def read(self):#基类中的函数只是给子类框个规范的框架,让子类如此构建框架,并不需要实例化和具体化,子类在具体和实例化
#         pass
#
#     @abc.abstractmethod
#     def write(self):
#         pass
# class Disk(All_file):
#     def read(self):
#         print('disk read')
#
#     def write(self):
#         print('disk write')
#
# class Cdrom(All_file):
#     def read(self):
#         print('cdrom read')
#
#     def write(self):
#         print('cdrom write')
#
#
# class Mem(All_file):
#     def read(self):
#         print('mem read')
#     def write(self):
#         print('mem write')
# m1=Mem()
# m1.read()# mem read
# m1.write()#mem write #即接口规定的属性,子类就必须继承,否则无法实例化


# class A:
#     # def test(self):
#     #     print('A')
#     pass
# class B(A):
#     # def test(self):
#     #     print('B')
#
#     pass
# class C(A):
#     # def test(self):
#     #     print('C')
#     pass
#
# class D(B):
#     # def test(self):
#     #     print('D')
#     pass
#
# class E(C):
#     # def test(self):
#     #     print('E')
#     pass
#
# class F(D,E):
#     # def test(self):
#     #     print('F')
#     pass
# f1=F()
# f1.test()   #通过逐一的关闭,测出其调用的顺序是经典类按深度找:F->D->B->A-->E-->C
#
# print(F.__mro__) #也可以通过__mro__来直接查看调用顺序#F-->D->B-->E--->C--->A新式类


#子类中调用父类:
# class Vehicle:
#     Country='China'
#     def __init__(self,name,speed,load,power):
#         self.name=name
#         self.speed=speed
#         self.load=load
#         self.power=power
#     def run(self):
#         print('开动啦')
#         print('开动啦')
# class Subway(Vehicle):
#         def __init__(self,name,speed,load,power,line):
#            Vehicle.__init__(self,name,speed,load,power)
#            self.line=line
#
#         def show_info(self):
#             print(self.name,self.speed,self.load,self.power,self.line)
#
#         def run(self):
#             Vehicle.run(self)
#             print('%s %s 线,开动啦' %(self.name,self.line))
# line13=Subway('北京地铁','10km/s',1000000000,'电',13)
#
# line13.show_info()#北京地铁 10km/s 1000000000 电 13
# # 子类有自己的属性如何调用父类的属性,就是子类里直接在调用父类的函数上,在添加自己的
# line13.run()# 开动啦 开动啦 北京地铁 13 线,开动啦
# 缺点是父类的名称一改,所以对应子类调用的父类函数都要一一修改,所以就出现了super()来代替父类函数的方法
#使用super()方法的好处:1 不用写父类名了,所以父类名改了,不用一一修正子类 2 不用传self参数了
class Vehicle1:
    Country='China'
    def __init__(self,name,speed,load,power):
        self.name=name
        self.speed=speed
        self.load=load
        self.power=power
    def run(self):
        print('开动啦')
        print('开动啦')
class Subway(Vehicle1):
        def __init__(self,name,speed,load,power,line):
           # Vehicle.__init__(self,name,speed,load,power)
           super().__init__(name,speed,load,power)  #super(__class__,self).__init__(name,speed,load,power)
           #super(Subway,self).__init__(name,speed,load,power)=super().__init__(name,speed,load,power),所以super后面不用传self参数
           self.line=line
        def show_info(self):
            print(self.name,self.speed,self.load,self.power,self.line)
        def run(self):
            # Vehicle.run(self)
            super().run()
            print('%s %s 线,开动啦' %(self.name,self.line))
line13=Subway('北京地铁','10km/s',1000000000,'电',13)
line13.show_info()#北京地铁 10km/s 1000000000 电 13
line13.run() #开动啦 开动啦 北京地铁 13 线,开动啦

print(line13.__class__) #<class '__main__.Subway'>

3 多态

class H2O:
    def __init__(self,name,temperature):
        self.name=name
        self.temperature=temperature
    def turn_ice(self):
        if self.temperature < 0:
            print('[%s]温度太低结冰了' %self.name)
        elif self.temperature > 0 and self.temperature < 100:
            print('[%s]液化成水' %self.name)
        elif self.temperature > 100:
            print('[%s]温度太高变成了水蒸气' %self.name)
    def aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(self):
        pass

class Water(H2O):
    pass
class Ice(H2O):
    pass
class Steam(H2O):
    pass

w1=Water('水',25)
i1=Ice('冰',-20)
s1=Steam('蒸汽',3000)

w1.turn_ice()
i1.turn_ice()
s1.turn_ice()

面向对象初级知识的介绍,总结如下:

  • 面向对象是一种编程方式,此编程方式的实现是基于对  和 对象 的使用
  • 类 是一个模板,模板中包装了多个“函数”供使用
  • 对象,根据模板创建的实例(即:对象),实例用于调用被包装在类中的函数
  • 面向对象三大特性:封装、继承和多态

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值