python面向对象编程

目录

一、开篇

1、什么是面向对象?

2、为什么要面向对象编程?

二、面向对象的基本概念

1、类和对象

1.1类是什么

1.2类的组成

1.2.2类属性vs实例属性

1.2.3类属性修改和访问

1.2.4私有化属性

1.2.5property属性函数

1.3对象是什么?

1.4对象怎么创建

2、方法

2.1实例方法 

2.2类方法

2.3静态方法

2.4__init__(self)方法

2.5魔术方法

2.5.1__str__方法

2.5.2__del__方法

2.6私有化方法

三、对象的三大基本特征

1、继承

1.1单继承

1.2多继承

1.3继承传递

1.4父类的重写

1.5调用父类的方法

2、封装

3、多态


一、开篇

1、什么是面向对象?

第一个问题,先来看下百度百科的解释:

面向对象编程(Object Oriented Programming,OOP,面向对象程序设计)的主要思想是把构成问题的各个事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描叙一个事物在整个解决问题的步骤中的行为。面向对象程序设计中的概念主要包括:对象、类、数据抽象、继承、动态绑定、数据封装、多态性、消息传递。通过这些概念面向对象的思想得到了具体的体现。 

简单理解,就是一种程序设计的思想,在程序设计中,利用对象去解决问题。

2、为什么要面向对象编程?

第二个问题,同样,再看下百度百科里的解释:

“面向过程”和“面向对象”

面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了;面向对象是把构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描叙某个事物在整个解决问题的步骤中的行为。

简单理解,面向过程做的事,就是按照业务逻辑从上到下写代码,每一步做什么,怎么实现,然后面向过程做完了,可以将功能代码封装到函数里,面向对象则关注谁来去做每一步,是更抽象的一种思想,里面将数据和函数绑定到一起,进行封装,减少了代码的重复重写。面向对象有三大基本特征:封装、多态、继承,这个在后面详细展开。

二、面向对象的基本概念

1、类和对象

1.1类是什么

类是一个模版,类里面可以包含多个函数,函数里面可以去实现一些功能。

1.2类的组成

类名+类的属性+类的方法

以下是一个类的例子

#创建一个类 (object)可省略
class Person(object):
    #类的属性
    name = 'LiMing'
    age = 35
    #类的方法 以def开头的函数
    def eat(self):
        print("eat")

    def run(self):
        print("run")
1.2.2类属性vs实例属性

如上面,name、age都是类属性

定义在类里面,实例方法外面,可通过类对象和实例对象访问。

定义在方法里面使用self引用的属性,称为实例属性,具体见__init__(self)方法,只能通过实例对象访问。

如以下代码所示:

class Biology:
    LB = "type"
    def __init__(self,name):
        self.name = name
#类属性通过类对象访问
zw1 = Biology.LB
#类属性通过实例方法访问
zw2 = Biology("zw").LB
#实例属性只能通过实例方法访问
dw1 = Biology("dxm").name
print(zw1)
print(zw2)
print(dw1)
1.2.3类属性修改和访问

在类外修改类属性,必须通过类对象去修改类属性。

通过实例对象修改,只会产生一个同名的实例属性,改的只是实例属性,不会影响到类属性。

class Biology:
    LB = "type"
    def __init__(self,name):
        self.name = name
#通过类对象修改类属性 再次访问时已经修改
Biology.LB = 'xm'
print(Biology.LB)
#通过实例对象修改类属性,再次访问并未修改
Biology("DXM").LB = "XXM"
print(Biology.LB)
1.2.4私有化属性

如果不想随意通过类名修改类属性,保护属性的安全,这时需要怎么做?

这时引出属性的私有化的概念。

语法:两个下划线开头,声明该属性为私有,不能在类的外部被使用或直接访问

示例如下:

class Biology:
    __LB = "type" #定义一个私有化属性,属性前面加两个下划线
XM = Biology()
print(XM.__LB) #实例对象无法访问私有属性
print(Biology.__LB) #类对象无法访问私有类属性

那私有化属性能否在类里面修改、访问呢?

答案是可以的,看示例代码

输出:type lei

class Biology:
    __LB = "type" #定义一个私有化属性,属性前面加两个下划线
    #访问私有属性
    def breathe(self):
        return Biology.__LB
    #修改私有属性
    def xg(self):
        Biology.__LB = "lei"
XM = Biology()
#打印出breathe这个实例方法访问到的私有属性的值
print(XM.breathe())
XM.xg()
#调用修改私有属性的xg实例方法后,再次访问时,私有属性值已经修改掉了
print(XM.breathe())

 那在类里可以访问修改,在子类里能否访问呢?(这里涉及到继承相关,可先移步继承那块

示例如下,结果抛异常:'Animal' object has no attribute '_Animal__name'

class Biology:
    # 定义一个私有化属性
    def __init__(self):
        __name = 'name'
class Animal(Biology):
    def eat(self):
        #尝试访问父类的私有实例属性
        print(self.__name)
XM = Animal()
XM.eat()
1.2.5property属性函数

前面访问私有变量时,访问、修改,是写了方法去控制,能否有其他的访问方式?

python提供了属性函数:property

具体应用方式请看示例代码

第一种方式:要求方法必须以set、get开头

class Biology:
    def __init__(self):
        self.__breathe = 'breathe'
    def set_eat(self,name):
        self.__breathe = name
        return self.__breathe
    def get_eat(self):
        return self.__breathe
    #定义一个属性,这里实例方法必须以set、get开头
    breathe = property(get_eat,set_eat)

XM = Biology()
XM.breathe = 'hello'
print(XM.breathe)

第二种方式:在方法上使用装饰器

@property是用于访问的,@函数名.setter是用于修改的

注意:这里访问和修改的函数名要一致。

class Biology:
    def __init__(self):
        self.__breathe = 'breathe'
    @property #对函数run进行装饰,提供一个getter方法
    def run(self):
        return self.__breathe
    @run.setter #使用装饰器进行装饰,提供一个setter
    def run(self,name):
        self.__breathe = name
        return self.__breathe

XM = Biology()
# XM.run = 'hello'
print(XM.run)

1.3对象是什么?

对象是根据模版创建的实例,可以通过实例对象去执行类中的函数。

1.4对象怎么创建

对象名=类名()

例子:创建一个对象

#创建一个叫LiMing的对象
LiMing = Person()
#调用Person类里的方法
LiMing.eat()
LiMing.run()
#访问类属性
print(LiMing.age)

2、方法

2.1实例方法 

使用关键字def定义,第一个行参默认传实例对象本身,一般使用self做为第一个参数。

在类的组成示例代码中,eat、run都是实例方法

2.2类方法

类对象拥有的方法,用装饰器@classmethod来标识其为类方法,第一个参数必须是类对象,一般以cls作为第一个参数,类方法可以通过类对象,实例对象调用

示例代码如下,打印结果:

type (引用的类属性)

None(因为函数无返回值)

class Biology:
    LB = "type"
    def __init__(self,name):
        self.name = name
    #类方法用classmethod来装饰
    @classmethod
    def breathe(cls):
        print(cls.LB)
# XM = Biology("DXM")
#获取类属性
print(Biology.breathe())

2.3静态方法

类对象拥有的方法,用@staticmethod来表示静态方法,静态方法不需要参数。

代码如下,打印结果:type yes

class Biology:
    LB = "type"
    def __init__(self,name):
        self.name = name
    #静态方法,用装饰器staticmethod来装饰
    @staticmethod
    def breathe(): #无需传递任何参数
        print(Biology.LB)
        return 'yes'
# XM = Biology("DXM")
#获取类属性
print(Biology.breathe())

2.4__init__(self)方法

关于属性,可以添加类属性,也可以创建对象后,去添加属性。

创建对象时,调用类属性,则用到了__init__(self)方法

代码如下,实例化对象时,传递实参:Name,Age

self和对象指向的是同一个内存地址,self是对象的引用

class Person(object):
#初始化的方法
    def __init__(self,Name,Age):
        self.name = Name
        self.age = Age
LiHua = Person('LiHua','40')
print(LiHua.name)
print(LiHua.age)

2.5魔术方法

__init__方法是一个魔术方法,经常在初始化类时使用,创建实例对象为其赋值

此外,还有常用的几个魔术方法

2.5.1__str__方法

注意:__str__方法只能return一个字符串

打印对象时,会执行这个方法,输出结果:LiHua的年龄是40

class Person(object):
    def __init__(self,Name,Age):
        self.name = Name
        self.age = Age
    def __str__(self):
        return '{}的年龄是{}'.format(self.name,self.age)
LiHua = Person('LiHua','40')
print(LiHua)
2.5.2__del__方法

析构方法:当一个对象被删除或销毁时,python解释器也会默认调用__del__这个方法

如下代码,程序执行完成后会自动调用__del__这个方法

手动删除时,也会调用__del__这个方法

析构函数一般用于资源的回收。

class Person(object):
    def __init__(self,Name,Age):
        self.name = Name
        self.age = Age
    def __del__(self):
        print('__del__方法被销毁')
LiHua = Person('LiHua','40')
print(LiHua)

python中魔术方法还有很多,感兴趣的可以扩展下,可参考下面的这篇博客,整理的很不错。Python中最全魔术方法整理_python魔术方法_程序猿-张益达的博客-CSDN博客在Python中set集合要求数据类型是可哈希的,因为set集合会默认调用对象的__hash__函数进行快速查询,如果找到了则调用对象的__eq__判断两个是是否相同,如果相同则不添加。如果抛出AttributeError异常,则会直接调用__getattr__方法,因为属性没有找到,__getattribute__方法中为了避免在该方法中无限递归,它的实现应该永远调用基类的同名方法以访问需要的任何属性。__call__()方法可以让类的实例具有类似于函数的行为,这进一步模糊了函数和对象之间的概念。_python魔术方法https://blog.csdn.net/weixin_41951954/article/details/128801577?ops_request_misc=&request_id=&biz_id=102&utm_term=python%20%E9%AD%94%E6%9C%AF%E6%96%B9%E6%B3%95&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-2-128801577.142%5Ev88%5Econtrol_2,239%5Ev2%5Einsert_chatgpt&spm=1018.2226.3001.4187

2.6私有化方法

前面属性提到了私有化属性,那同理,方法能不能私有化呢?

答案是可以的,有的重要的方法,不允许外部调用,防止子类意外重写,可以把普通的方法设置成私有化方法。

私有化方法也是在方法名前加两个下划线。

示例代码如下:

class Biology:
    #普通实例方法
    def eat(self):
        print('eat')
    #私有化方法
    def __breathe(self):
        print('breathe')

XM = Biology()
#调用普通实例方法 可以调用成功
XM.eat()
#调用私有化方法抛出异常:'Biology' object has no attribute '__breathe'
XM.__breathe()

私有化方法也是可以内部调用的,但外部不能调用,子类也不能继承

扩展关于python命名中下划线的应用,可以看看这篇博客,写得很清晰。

Python 类的下划线命名_dta0502的博客-CSDN博客类的下划线命名1、 _xx 以单下划线开头的表示的是protected类型的变量。即保护类型只能允许其本身与子类进行访问。若内部变量标示,如: 当使用“from a_module import”时,不会将以一个下划线开头的对象引入 。不过值得注意的是,如果使用 import a_module 这样导入模块,仍然可以用 a_module._some_var 这样的形式访问到这样的对象。2、 __xx...https://blog.csdn.net/dta0502/article/details/80769191

三、对象的三大基本特征

1、继承

1.1单继承

子类继承父类

继承的方法,类名+(父类),父类的属性、实例方法会继承给子类

class Animal(object):
    def eat(self):
        print("eat")
class Person(Animal):
    pass
LiMing = Person().eat()

1.2多继承

Person类可继承Biology、Animal中的方法,同时拥有Biology、Animal的属性和方法。

类名+(父类1,父类2……) 可继承多个父类

class Biology:
    def breathe(self):
        print('breathe')
class Animal(object):
    def eat(self):
        print("eat")
class Person(Animal,Biology):
    pass
LiMing = Person().eat()
LiHua = Person().breathe()

 有个问题,如果多个父类中有同名的实例方法,这时应该去继承哪个?继承顺序是怎么样的?

class Biology:
    def breathe(self):
        print('biology,breathe')
class Animal(object):
    def eat(self):
        print("eat")
    def breathe(self):
        print('Animal,breathe')
class Person(Animal,Biology):
    pass
LiHua = Person().breathe()
print(Person.__mro__)

输出结果如下: 

Animal,breathe
(<class '__main__.Person'>, <class '__main__.Animal'>, <class '__main__.Biology'>, <class 'object'>)

用__mro__函数查看一下,代码查找顺序为Person、Animal、Biology

在Biology中找到后就不再往后找了,是按继承时括号里的顺序进行查找的。

1.3继承传递

子类继承父类,但如果父类又继承了父类呢?子类是否能继承父类的父类呢?

看代码,结果是Person可以继承父类Animal的父类Biology的。

父类称为基类,子类称为派生类。父类的属性和实例方法可以一级一级传递下去,这就是继承的传递性。

class Biology:
    def breathe(self):
        print('biology,breathe')
class Animal(Biology):
    def eat(self):
        print("eat")
class Person(Animal):
    pass
LiHua = Person().breathe()
print(Person.__mro__)
biology,breathe
(<class '__main__.Person'>, <class '__main__.Animal'>, <class '__main__.Biology'>, <class 'object'>)

1.4父类的重写

如下代码,Animal类继承了Biology类,但有重写了breathe方法,此时子类中的方法会覆盖掉父类同名的方法,执行结果为:Animal,breathe

class Biology:
    def breathe(self):
        print('biology,breathe')
class Animal(Biology):
    def eat(self):
        print("eat")
    def breathe(self):
        print('Animal,breathe')
dxm = Animal().breathe()

1.5调用父类的方法

三种在子类中调用父类的方法:

super(Animal,self).__init__(name)
super().__init__(name)
Biology.__init__(self,name)
class Biology:
    def __init__(self,name):
        self.name = name

class Animal(Biology):
    def __init__(self,name):
        super(Animal,self).__init__(name)
        # super().__init__(name)
        # Biology.__init__(self,name)
        self.name += 'hello'
        print(self.name)
dxm = Animal('xm')

2、封装

把内容封装到某个地方,便于后面的调用

需要满足:内容封装到一处,从另外一处调用被封装内容

将初始化构造方法将内容封装到对象中,然后通过对象直接或者self来获取被封装的内容

3、多态

百度百科里多态的解释:

编程语言类型论中,多态(英语:polymorphism)指为不同数据类型的实体提供统一的接口

例子举的很形象:比如有动物(Animal)之类别(Class),而且由动物继承出类别鸡(Chicken)和类别狗(Dog),并对同一源自类别动物(父类)之一消息有不同的响应,如类别动物有“叫()”之动作,而类别鸡会“啼叫()”,类别狗则会“吠叫()”,则称之为多态。

简而言之,就是同一个接口,有不同的实现方式,具体可参考下面的这篇博客,写的很清楚。

python中对多态的理解_python多态的理解_BlazarBruce的博客-CSDN博客一、多态多态是指一类事物有多种形态,比如动物类,可以有猫,狗,猪等等。(一个抽象类有多个子类,因而多态的概念依赖于继承)import abcclass Animal(metaclass=abc.ABCMeta): #同一类事物:动物 @abc.abstractmethod def talk(self): passclass Cat(Animal): #动物的形态之一:猫 def talk(self): print('say miaomi_python多态的理解https://blog.csdn.net/qq_39820671/article/details/107833171

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MRJJ_9

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值