Python中的面向对象-OOP

本文介绍了Python的面向对象编程(OOP),包括面向过程与面向对象的区别、类与对象的概念、面向对象编程的基本实现、成员属性和成员方法的操作、self的使用、方法的分类以及魔术方法。此外,还探讨了初始化方法和析构方法,并提供了一个日志类的封装实践。
摘要由CSDN通过智能技术生成

面向对象-OOP

面向对象编程——Object Oriented Programming,简称OOP,是一种以对象为中心的程序设计思想。

面向过程编程——Procedure Oriented Programming,简称POP,是一种以过程为中心的程序设计思想。

##1.面向过程与面向对象

###区别和优缺点:

  • 面向过程:

    遇到问题后,分析解决问题的步骤,然后一步步去实现;面向过程的核心是过程,过程就是指解决问题的步骤。

    优缺点:

    • 优点:将负责的问题流程化,进而实现简答化
    • 缺点:扩展性差(更新,维护,迭代)

    总结:在去完成一些简单的程序时,可以使用面向过程去解决。但是如果有复杂的程序或任务,而且需要不断的进行迭代和维护,那么肯定是优先选择面向对象的编程思想

  • 面向对象:

    通过分析问题中需要的抽象模型,然后根据需要的功能分别去创建模型对象,最终由模型对象来完成程序;面向对象的核心是对象,是一个特征和功能的综合体。

    ​ 面向对象就是调用对象去解决问题,所以首先需要先建立出对象的抽象模型,就是建立。然后对象(也就是在类中)通过面向过程来一步步去解决问题。但是对于我们来说,就是调用了对象,然后问题就被对象解决了。

    优缺点:

    • 优点:可扩展性高
    • 缺点:编程的复杂度相对面向过程要高一些。指的是计算机在执行面向对象的程序时的性能表现。

###认识类与对象:

类:类是对象的抽象概念;

对象(实例):对象就是由类创建的实例;

类和对象的关系就是 模具与成品的关系:

  1. 类是由对象总结而来的,总结的这个过程叫做抽象;
  2. 对象是由类具体实施出来的,这个过程叫做实例化。
  • 水果是类,具体的某种水果-比如苹果,就是一个对象;
  • 手机是类,具体的某种手机-比如小米,就是一个对象;
  • 笔记本电脑是一个具体的实实在在存在的东西,是一个对象。

##2.面向对象编程的基本实现

如果需要创建一个对象,那么需要先建立一个抽象的模型,就是

然后由类实例出对象

例如需要创建一个汽车对象:

首先:需要抽象一个汽车类,汽车类就相当于一个设计图纸一样;

然后:由设计图纸去创建(实例)出来的真实汽车,就是一个对象。

  • 通过class关键字来定义一个类:
#定义一个汽车类
class Car():
    pass
  • 类名的书写规范,使用驼峰命名法:

    '''
    类名的书写规范,建议使用驼峰命名法
        大驼峰:MyCar XiaoMi    #每个单词的首字母大写
        小驼峰:myCar xiaoMi    #第二个单词的首字母大写
    '''
    
  • 类中需要声明的两个内容:

    1. 属性:是一个变量,描述对象有什么特征
    2. 方法:是一个函数,实现对象有什么功能
    类中属性一般定义在前面,方法定义在后面
    
    #定义一个汽车类Car
    class Car():
        #定义属性:用变量来描述类的特征
        color = '白色'
        brand = '奥迪'
    
        #定义方法:用函数来实现类的功能
        def drive(self):
            print('可以开车')
    
  • 通过类实例化对象并使用:

    class Car():
        #定义属性:用变量来描述类的特征
        color = '白色'
        brand = '奥迪'
    
        #定义方法:用函数来实现类的功能
        def drive(self):
            print('可以开车')
    
    #通过类实例化对象:调用类,此时a就是对象
    a = Car()  
    print(a)
    print(type(a))
    >>><__main__.Car object at 0x000001638CB822C8> 
       <class '__main__.Car'>
    
    #调用对象的方法
    a.drive()
    print(a.drive())
    >>>可以开车
       None
    #【注意!这里的drive()函数里是print而不是return,所以直接a.drive()就可以输出,不能print(a.drive()),不然返回值是None】
    #【怎么老是弄混这一点】
    
    #调用对象的属性
    print(a.color)
    >>>白色
    
    【这里就属于在类的外部使用对象操作成员】
    

2.1成员属性和成员方法的操作

2.1.1. 对象操作成员:在类的外部进行
'''
什么是对象的成员?
一个对象通过类实例化之后,那么在类中定义的属性和方法,就叫做成员,可以使用实例化的对象进行操作;
类中定义的属性也称为 成员属性,
类中定义的方法也称为 成员方法;

成员属性的作用就是存储信息,供成员方法使用
'''
#定义一个Car类
class Car():
    #定义属性:用变量来描述类的特征
    color = '白色'
    brand = '奥迪'

    #定义方法:用函数来实现类的功能
    def drive(self):
        print('可以开车')

a = Car()
b = Car()
print(a)
print(b)
>>><__main__.Car object at 0x0000020019F72308>
   <__main__.Car object at 0x0000020019F72608>
'''
一个类可以实例化多个对象;
以上的a和b变量都是对象,也都是通过Car这个类实例化出来的对象,
但是通过id地址可以看出,a和b是两个对象,它俩相同之处就在于都同由同一个类实例化出来。
'''

#####使用对象操作成员属性

  • 访问对象成员属性:

    先访问a对象自己的属性,如果没有就去访问这个对象的类的属性(也就是成员属性)

#通过对象访问类中的属性
print(a.color)
>>>白色
  • 修改对象的成员属性:

    实际上等于给当前对象创建了一个自己的color属性;

    重新定义这个对象的color属性;

    a.color = '黑色'
    print(a.color)
    print(b.color)   #此时,b对象的color属性依然原来的值
    >>>黑色
       白色
    
  • 添加对象的属性:

    给当前对象创建了自己独有的name属性

    #给当前a对象添加自己独有的属性
    a.name = 'che'
    #此时b对象没有name属性
    
  • 删除对象的属性:

    只能删除这个对象自己的属性:给对象添加的属性和修改的属性,这个对象的类的属性不能删除

    #只能删除这个对象自己的属性:给对象添加的属性和修改的属性
    a.color = 'che'
    print(a.color)
    del a.color
    print(a.color)
    >>>che
       白色
    #删除修改的属性之后,对象的该成员属性值就变成了类里面的属性值
    #注意!如果此时再del a.color就会报错,因为只能删除当前这个对象自己的属性,此时的color属性是属于类Car的。
    

#####使用对象操作成员方法

  • 访问成员方法:

    如果这个对象没有自己独立的方法,那么会访问这个对象的类的方法(也就是成员方法)

    a.drive()
    >>>可以开车
    
  • 修改对象的成员方法:

    实际上等于给当前对象创建了一个自己的方法;

    重新定义这个对象的成员方法;

    def func():
        print('这是一个新方法')
    a.drive = func    #把一个函数赋值给成员方法
    a.drive()         #调用方法
    >>>这是一个新方法
    【注意!函数名后面带上括号就是调用,所以赋值的时候千万不要带括号!】
    
  • 添加对象的方法:

    给当前对象创建了自己独有的new方法

    def func():
        print('添加一个方法')
    a.new = func
    a.new()
    >>>添加一个方法
    
  • 删除对象的方法:

    只能删除这个对象自己的方法:给对象添加的方法和修改的方法,这个对象的类的方法不能删除

    def func():
        print('添加一个方法')
    a.drive = func    #修改
    a.new = func      #添加
    a.drive()
    a.new()
    del a.drive       #删除修改
    a.drive()
    del a.new         #删除添加
    #a.new()          #这里此时会报错,因为已经没有这个方法了
    #del a.drive      #这里也会报错,因为不能删除对象的类的方法
    
    >>>添加一个方法
       添加一个方法
       可以开车
    
'''
总结:
一个类定义了类成员属性和成员方法,那么通过这个类实例化的对象,也具备这些方法和属性吗?
    实际上,创建对象的时候,并不会把类中的属性和方法复制一份给对象,而是在对象中引用父类的方法。
    因此在访问对象的属性时,会先去找对象自己的属性,如果没有就去找这个类的属性和方法。

一个对象由类实例化以后,是一个独立的对象,会引用父类中的属性和方法;
    如果在对象创建后,给对象的属性或方法,进行修改或添加,那么此时等于给这个对象创建了一个自己的属性和方法,
    所以在删除时,只能删除对象被修改或添加的成员。
'''
'''
总结:
成员属性:
  访问:  对象.成员属性名
  修改:  对象.成员属性名 = 新值(此时等于给这个对象创建了一个自己的属性)
  添加:  对象.新属性名 = 值 (此时是给这个对象自己新建了一个属性)
  删除:  del 对象.属性名 (注意:只能删除这个对象自己的属性)
  
成员方法:
  访问:  对象.成员方法名()
  修改:  对象.成员方法名 = func(此时等于给这个对象创建了一个自己的方法)
  添加:  对象.新方法名 = func (此时是给这个对象自己新建了一个方法)
  删除:  del 对象.方法名 (注意:只能删除这个对象自己的方法)
'''
2.1.2 类操作成员(不推荐)

在类的外部,可以直接通过类对成员进行操作

#定义一个Car类
class Car():
    #定义属性:用变量来描述类的特征
    color = '白色'
    brand = '奥迪'

    #定义方法:用函数来实现类的功能
    def drive(self):
        print('可以开车')

#####类成员属性的操作

  • 访问类成员属性:
print(Car.color)
>>>白色
  • 修改类成员属性:

    如果通过类把属性进行修改,那么再通过这个类实例化的对象,它的属性是会变成修改之后的值;

    在类属性修改前创建的对象的属性也会变成修改之前的值。

    a = Car()
    Car.color = '黑色'
    b = Car()
    print(Car.color)
    print(b.color)  # 是修改后的结果
    print(a.color)  # 在类属性修改前创建的对象的属性也被修改
    >>>黑色
       黑色
       黑色
    
  • 添加类成员属性:

    添加之前创建的对象和之后创建的对象都会有这个新的属性

    a = Car()
    Car.zxc = '瞎写的'
    b = Car()
    print(Car.zxc)
    print(a.zxc)
    print(b.zxc)
    >>>瞎写的
       瞎写的
       瞎写的
    
  • 删除类成员属性:

    删除之前和之后创建的对象,都没有这个属性了

    a = Car()
    Car.zxc = '瞎写的'
    b = Car()
    del Car.zxc
    del Car.color    #可以删除类里面的属性
    #此时a和b都没有这个属性了
    

#####类成员方法的操作

【同上】

'''
总结:
成员属性:
  访问:  类名.成员属性名
  修改:  类名.成员属性名 = 新值。(此时通过这个类创建的对象都具有这个属性)
  添加:  类名.新成员属性 = 值 (此时通过这个类创建的对象都具有这个属性)
  删除:  del 类名.成员属性 (注意:删除这个类的属性后,这个类创建的对象也没有这几个属性了)
  
成员方法:
  访问:  类名.成员方法名()
  修改:  类名.成员方法名 = func(此时通过类创建的对象都被修改)
  添加:  类名.方法名 = func (此时通过类创建的对象都被修改)
  删除:  del 类名.方法名 (注意:此时通过类创建的对象都被修改)
'''

####2.1.3.总结

  • 一个类可以实例化出多个对象,每个对象在内存中都独立存在的
  • 当通过类实例化对象时,并不会把类中的成员复制一份给对象,而去给对象了一个引用
  • 访问对象成员的时候,如果对象自己没有这个成员,对象会向实例化它的类去查找
  • 对象成员的添加和修改,都只会影响当前对象自己,不会影响类和其它对象
  • 删除对象的成员时,必须是该对象自己具备的成员才可以,不能删除类中引用的成员
  • 对类的成员操作,会影响通过这个类创建的对象,包括之前创建的。

2.2 成员方法中的self

  • self在方法中只是一个形参,并不是关键字;
  • self 单词本身的意思:自己;
  • self 在类的方法中代表当前这个对象;
  • self 代表调用这个方法的对象,谁调用了这个方法,self就代表谁
  • self 就可以在类的内部代替对象进行各种操作,要是对象能干的事,self都可以代表对象去完成;
  • 如果成员方法中不含self形参,则该方法是绑定类方法,不能使用对象去调用,只能使用类去访问。

2.3 方法的分类

  • 含有self或者可以接受对象作为参数的方法: 非绑定类方法
  • 不含self或者不能接受对象作为参数的方法:绑定类方法

非绑定类方法,只能使用对象去访问,如果使用类去访问就会报错;

绑定类方法,只能使用类去访问。

###2.4 魔术方法

魔术方法也和普通方法一样都是类中定义的成员方法
魔术方法不需要手动调用,魔术方法会在某种情况下自动执行;
魔术方法还有一个比较特殊的地方:多数的魔术方法前后都有两个连续的下划线
魔术方法不是我们自己定义的,而是系统定义好的,我们来使用。

__init__初始化方法:类实例化对象时自动触发
  • 触发机制:在通过类实例化对象后,自动触发
  • 作用:可以在对象实例化后完成对象的初始化(属性的赋值,方法的调用)
  • 应用场景: 文件的打开,数据的获取等等干活前的一些准备功能
class Person():
    # 成员属性
    name = None
    age = None
    sex = None

    # __init__ 初始化方法
    def __init__(self,n,a,s):
        # print('我是一个初始化方法')
        # 完成对象属性的初始化
        self.name = n
        self.age = a
        self.sex = s
        # 调用方法
        self.say()

    # 成员方法
    def say(self):
        print(f'大噶好,唔系{self.name},系兄弟就来砍我。。')

# 实例化对象
# zzh = Person()
zzh = Person('渣渣灰',56,'男')

####__del__析构方法:对象被销毁时自动触发

  • 触发机制:在对象被销毁时,自动触发

  • 作用:关闭一些开发的资源,比如在初始化方法中开发的文件,可以在析构方法中关闭
    【注意!是对象被销毁时触发了析构方法,而不是析构方法销毁了对象】

  • 对象会在哪些情况被销毁?

    【按照以下顺序】

    • 首先,如果使用了del删除【这里的首先也包括“del删除”在“对象不再被引用”之前!如果先是“对象不再被引用”,那么就先销毁这个对象】;
    • 其次,对象不再被引用时【也就是类操作成员时】,会自动销毁【这里的其次也包括“对象不再被引用”在“del删除”之后!】;
    • 最后,如果以上两种都不存在,则当程序执行完毕,内存中所有的资源都会被销毁释放

    【如果这里不好理解,去看最后那个汽车类的例子!】

示例:

定义一个类,完成一个日志的记录
调用这个对象的时候,传递一个日志信息
这个对象会创建一个文件,开始写入,并在最后关闭这个文件

import time

class writeLog():
    # 成员属性
    # 文件的路径
    fileurl = './'
    # 日志文件的名称
    filename = '2019-09-19'

    # 初识化  打开文件
    def __init__(self):
        #完成文件的打开
        print('初始化方法触发类。完成文件的打开')
        self.fileobj = open(self.fileurl+self.filename,'a+',encoding='utf-8')

    # 写日志的方法
    def log(self,s):
        print(f'把日志:{s} 写入文件中')

    # 析构方法
    def __del__(self):
        print('析构方法触发了,关闭打开的文件')
        # 在对象被销毁时,关闭在初始化方法中打开的文件对象
        self.fileobj.close()

【注意以下程序的执行结果!】

#定义汽车类
class Cart():
    brand = ''

    def __init__(self,b):
        self.brand = b
        print(f'初始化方法被触发:创建{self.brand}汽车')

    def __del__(self):
        print(f'析构方法被触发:{self.brand}汽车已经销毁了')
        
        
【问题1:下面程序的执行结果】
bm = Cart('宝马')
bc = Cart('奔驰')
fll = Cart('法拉利')

【这种销毁对象的情况属于“当程序执行完毕,内存中所有的资源都会被销毁释放”】
【结果为:】
'''
1 宝马创建
2 奔驰创建
3 法拉利创建
4 宝马被销毁
5 奔驰被销毁
6 法拉利被销毁
'''

【问题2:下面程序的执行结果】
Cart('宝马')
Cart('奔驰')
Cart('法拉利')
【这种销毁对象的情况属于“对象不再被引用时,会自动销毁”】
【结果为:】
'''
1 宝马创建
2 宝马销毁
3 奔驰创建
4 奔驰销毁
5 法拉利创建
6 法拉利销毁
'''


【注意析构方法被触发的三种情况的顺序!】
bm = Cart('宝马')
bc = Cart('奔驰')
del bc
Cart('法拉利')
【先找手动del(前提是del在类操作成员前面),然后找对象不再被引用(就是类操作成员),最后是程序执行结束】
【结果为:】
'''
1 宝马创建
2 奔驰创建
3 奔驰销毁
4 法拉利创建
5 法拉利销毁
6 宝马销毁
'''
【如果代码是:】
bm = Cart('宝马')
bc = Cart('奔驰')
Cart('法拉利')
del bc
【那么结果就是:】
'''
1 宝马创建
2 奔驰创建
3 法拉利创建
4 法拉利销毁
5 奔驰销毁
6 宝马销毁
'''

练习:日志类的封装

日志类
   class  Mylog
   功能:
       能够随时写入一个日志信息

分析:
   日志文件在什么地方? 默认在当前目录
   日志的文件名是什么? 当前日期 2019-09-20.log
   日志的格式是什么样的? 2019-09-20 12:12:12 接收的信息

   属性:成员属性的作用就是存储信息,供成员方法来使用的
       fileurl 日志文件的地址
       filename 日志文件的名称
       fileobj 打开的文件对象


   方法:具体完成的一个功能的过程
       __init__()  ==> 初始化方法,完成对象的初始化,并打开文件
       log()      ==> 负责接受用给的日志信息,并写入到日志文件中
       __del__()   ==> 析构方法,在对象被销毁时,关闭打开的文件
import time

#定义一个日志类
class myLog():
    #属性
    #fileurl = './'
    #filename = str(time.strftime('%Y-%m-%d')) + '.log'
    filename = './封装日志类生成的文件.txt'  #可以把上面俩直接合成这一个
    fp = None

    #初始化方法
    def __init__(self):
        #打开文件
        self.fp = open(self.fileurl + self.filename, 'a+', encoding='utf-8')

    #log()方法,s是给出的日志信息
    def log(self,s):
        #写入的时间
        date = time.strftime('%Y-%m-%d %H:%M:%S')
        s = date + ' ' + s + '\n'
        #写入信息
        self.fp.write(s)

    #析构方法
    def __del__(self):
        #关闭文件
        self.fp.close()

#实例化对象
a = myLog()
#调用方法
a.log('写的好!艰!难!')
a.log('大艺术家好!洗!脑!')

#这样就可以运行的时候写入
res = input('输入你要写的内容:')
a.log(res)
>>>输入你要写的内容:学不动了.jpg

此时文件的最后一行就多了:
2020-06-17 14:15:39 学不动了.jpg
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值