Python面向对象编程(一)类的基础,关系,继承,封装,多态

这篇具有很好参考价值的文章主要介绍了Python面向对象编程(一)类的基础,关系,继承,封装,多态。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

类的一些理论概念及其应用场景等基础内容此处不赘述

目录

python中一切皆对象

类的定义及基础

属性

方法

初始化方法

 普通方法

类之间的关系

相互调用

依赖关系

关联关系

组合关系

三大特征----类的继承

重写父类方法

多继承

混合继承 

三大特征----封装

三大特征----多态

isinstance 

抽象基类@abstractmethod


python中一切皆对象

python所有的数据类型都是对象,例如下面的a是int类的对象,b是str类的对象

a = 1
b = 'asc'
print(type(a))
print(type(b))
# <class 'int'>
# <class 'str'>

 而type创建了所有的类

class person:
    pass
print(type(int))
print(type(str))
print(type(list))
print(type(dict))
print(type(person))
# <class 'type'>
# <class 'type'>
# <class 'type'>
# <class 'type'>
# <class 'type'>

  所有类的的基类都是  object 

print(int.__bases__)
print(str.__bases__)
print(list.__bases__)
print(dict.__bases__)
# (<class 'object'>,)
# (<class 'object'>,)
# (<class 'object'>,)
# (<class 'object'>,)

  object是被type创建的,而type类的基类是object(type创建object的同时也继承了object)

print(type(object))
print(type.__bases__)
# <class 'type'>
# (<class 'object'>,)

类的定义及基础

类的一般定义:

class Name_of_Class:
    Shared_property=1
    def __init__(self):
        private_property=2
    def method(self):
        print(1)

类里包含了属性方法

属性

属性分为公共属性实例属性,上面的shared_property就是共有属性,private_property就是实例属性,区别在于:

公有属性是放在原始类的内存中的,如果发生改变,所有对象都会发生改变

私有属性是放在对象内存中的,如果改变只会改变该对象的值,是对象独享的

举个例子

class Name_of_Class:
    Shared_property=1
    def __init__(self):
        self.object_property=2

obj1=Name_of_Class()
obj2=Name_of_Class()

Name_of_Class.Shared_property=111

print(obj1.Shared_property)
print(obj2.Shared_property)

obj1.object_property=3
print(obj2.object_property)
# 111
# 111
# 2

那比如要设置一个  某个年级学生信息的类,就可以把 年级 作为公共属性,把一些身高体重等作为实例属性

但是如果对象把类的公共属性给改了,就相当于给对象创建了一个新的实例有属性

class Name_of_Class:
    Shared_property=1

obj1=Name_of_Class()
obj2=Name_of_Class()

obj1.Shared_property=111

print(obj1.Shared_property)
print(obj2.Shared_property)
# 111
# 1

方法

初始化方法

def __init__(self):
    pass

又叫做构造方法,构造函数,实例化的时候会自动运行

初始化方法可以设置参数,一般的格式是

class Name_of_Class:
    Shared_property=1
    def __init__(self,object_property1,object_property2):
        self.object_property1=object_property1
        self.object_property2=object_property2

调用方式是

obj1=Name_of_Class(2,3)
print(obj1.object_property1)
print(obj1.object_property2)
# 2
# 3

在进行实例化的时候直接传参就可以调用初始化方法

这里的self.object_property1=object_property1是确保将传进来的参数作为对象本身的实例属性保存起来,这里借用一张内存图说明

Python面向对象编程(一)类的基础,关系,继承,封装,多态,Python天下第一,python,开发语言

  1.  实例化时,申请一块内存空间
  2. 将实例化的参数传给__init__
  3. __init__将参数转为实例属性传给这个内存空间

 普通方法

class Name_of_Class:
    Shared_property=1
    def __init__(self,object_property1,object_property2):
        self.object_property1=object_property1
        self.object_property2=object_property2
    def method(self):
        print(self.object_property2+self.object_property1)

obj1=Name_of_Class(2,3)
obj1.method()
# 5

普通方法的参数同一有  self ,告知是哪个对象调用了方法

在普通方法中调用私有参数要  self.xxxx

类之间的关系

相互调用

只需要在定义类方法的时候将其他的对象作为参数传进去

class soilder:
    def __init__(self,name,m4):
        self.name=name
        self.m4=m4
        self.bloodall=100
    def attack_back(self,badperson):
        badperson.bloodall-=self.m4
        print('soilder [%s] attack badperson [%s],badperson has [%s] blood'%(self.name,badperson.name,badperson.bloodall))


class badperson:
    def __init__(self, name, ak):
        self.name = name
        self.ak = ak
        self.bloodall = 100

    def attack(self, soilder):
        soilder.bloodall -= self.ak
        print('badperson [%s] attack soilder [%s],soilder has [%s] blood'%(self.name,soilder.name,soilder.bloodall))


lee = soilder('lee',30)
liu =badperson('liu',35)

liu.attack(lee)
lee.attack_back(liu)

# badperson [liu] attack soilder [lee],soilder has [65] blood
# soilder [lee] attack badperson [liu],badperson has [70] blood

依赖关系

在依赖类的 初始化函数 中将master对象引入

class dog:
    def __init__(self,name,age,master):
        self.name=name
        self.age=age
        self.master=master
    def say(self):
        print('my master is ',self.master.name)

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

p1 = master('lee',23)
d1=dog('hhh',2,p1)

d1.say()

关联关系

这个通过一个例子来说明这种关系,生活中最常见的这种关系是  结婚

结婚是两个人一起结婚的,所以在这里最好定义一个新的类relationship来存储两个人的婚姻关系,这样可以保证避免了A和B结婚了但是B和A没结婚的bug出现

如果结婚了就调用get_marred函数,如果离婚就是diverse函数,状态存储在couple数组里面

person类中调用这个relation类进行操作,并且可以通过get_partner函数获取自己的伴侣

class relationship:
    def __init__(self):
        self.couple=[]
    def get_married(self,obj1,obj2):
        self.couple=[obj1,obj2]
        print(obj1.name,'and ',obj2.name,'get married')
    def diverse(self):
        self.couple=[]


class person:
    def __init__(self,name,age,sex,relation):
        self.name=name
        self.age=age
        self.sex=sex
        self.relation=relation
    def get_partner(self):
        for i in self.relation.couple:
            if i.name==self.name:
                continue
            else:
                return i.name

relationship_obj=relationship()
p1=person('lee',23,'M',relationship_obj)
p2=person('liu',22,'F',relationship_obj)
relationship_obj.get_married(p1,p2)
print(p2.get_partner())
relationship_obj.diverse()
print(p1.get_partner())
# lee and  liu get married
# lee
# None

组合关系

由一堆组件构成一个整体,组件自己独立但是不能自己运行,必须跟宿主结合,例如人的器官和人的关系

这里定义了一个器官类,里面有不同器官的函数

在定义person类时,直接 self.action=organs(),既实例化一个器官对象,那么每次实例化一个person都会实例化一个organs,器官和人就是组合关系

class organs:
    def __init__(self):
        self.name=None
    def heart(self):
        self.name = '心脏'
        print('心脏跳动了一下')
    def lung(self):
        self.name='肺'
        print('肺呼吸了一下')

class person:
    def __init__(self,name,age,sex):
        self.name=name
        self.age=age
        self.sex=sex
        self.action=organs()
    def get_partner(self):
        for i in self.relation.couple:
            if i.name==self.name:
                continue
            else:
                return i.name


p1=person('lee',23,'M')
p2=person('liu',22,'F')

p1.action.heart()
p1.action.lung()
# 心脏跳动了一下
# 肺呼吸了一下

三大特征----类的继承

类的继承是三大特征之一,主要的功能是使类A能得到类B的所有方法和属性而不需要重复书写代码,继承的方式就是在定义的时候加入父类的名字:

class son(father):
    pass

例如猪和人都是动物,那么可以抽象一个animal类,把动物该有的属性和方法加入,当然新定义的类也可以加入自己独有的方法,或者重构 原有父类的方法:

class animal:
    def __init__(self,name,age,sex):
        self.name=name
        self.age=age
        self.sex=sex
    def eat(self):
        print(111)


class pig(animal):
    pass

class person(animal):
    def eat(self):
        print(333)
    def thinking(self):
        print(222)


p1 = pig('liu',2,'M')
p2 = person('lee',23,'F')

p1.eat()
p2.thinking()
p2.eat()

# 111
# 222
# 333

重写父类方法

新定义的类也可以在原有类的基础上增加功能,而不完全重构

下面的代码在person继承了animal类,并且增加了初始化函数和普通方法的功能,主要思想就是在定义新的类的方法使,先运行父类的方法

class animal:
    def __init__(self,name,age,sex):
        self.name=name
        self.age=age
        self.sex=sex
    def eat(self):
        print(111)

class person(animal):
    def __init__(self,name,age,sex,hobby):
        animal.__init__(self,name,age,sex)
        self.hobby=hobby

    def eat(self):
        animal.eat(self)
        print(333)
    def thinking(self):
        print(222)


p2 = person('lee',23,'F','study')
print(p2.hobby)

p2.eat()

# study
# 111
# 333

在高版本的python中,还支持这种写法,其实结果是一样的:

class person(animal):
    def __init__(self,name,age,sex,hobby):
        super(person,self).__init__(name,age,sex)
        # animal.__init__(self,name,age,sex)
        self.hobby=hobby    
    def eat(self):
        super(person, self).eat()
        print(333)
    def thinking(self):
        print(222)

或者

class person(animal):
    def __init__(self,name,age,sex,hobby):
        super().__init__(name,age,sex)
        # animal.__init__(self,name,age,sex)
        self.hobby=hobby
    def eat(self):
        super().eat()
        print(333)
    def thinking(self):
        print(222)

多继承

 python是允许多继承的,也就是可以同时继承多个父类

当父类也有父类时,就有一个树状结构,此时继承顺序就很重要,这里有一个简单的例子

例如下面这种情况,同时继承了两个类,按照从左到右的顺序继承

class father(grandpa):
    def test(self):
        print('father')

class mother:
    def test(self):
        print('mother')

class son(father,mother):
    pass

p1=son()
p1.test()
#fatehr

再例如,当father类没有test时,会搜索father的父辈grandpa:

class grandpa:
    def test(self):
        print('grandpa')

class father(grandpa):
    pass

class mother:
    def test(self):
        print('mother')

class son(father,mother):
    pass

p1=son()
p1.test()
#grandpa

到这里为止,都很像深度优先搜索,但是其实不是,而是运用了C3算法比如当fater和mather类都继承自grandpa时

class grandpa:
    def test(self):
        print('grandpa')

class father(grandpa):
    pass

class mother(grandpa):
    def test(self):
        print('mother')

class son(father,mother):
    pass

p1=son()
p1.test()
# mother

为了方便,可以直接查看类的继承顺序

print(son.mro())
#[<class '__main__.son'>, <class '__main__.father'>, <class '__main__.mother'>, <class #'__main__.grandpa'>, <class 'object'>]

至于C3算法,有兴趣的可以看看这个 

Python 中多继承 C3-MRO 算法的剖析 - 知乎

混合继承 

当一个类bird继承了多个子类时,子类之间的方法可以直接调用,也能调用到最初始子类(annimal)的私有属性

class animal():
    def __init__(self,name):
        self.name = name

class Fly():
    def fly(self):
        print(f'{self.name} fly')

class Swim():
    def swim(self):
        print(f'{self.name} swim')


class Run():
    def run(self):
        print(f'{self.name} run')

class Bird(animal,Fly,Swim,Run):
    pass

bird = Bird('lmx')
bird.fly()
bird.swim()
bird.run()
# lmx fly
# lmx swim
# lmx run

 像上述Fly、Swim、Run这种类功能简单,易于维护,一般称为mixin

一般来说,mixin功能是单一的,且不能继承别的类

在使用mixin时尽量避免使用super

三大特征----封装

封装可以被认为是一个保护屏障,防止该类的代码和数据被外部类定义的代码随机访问。
要访问该类的代码和数据,必须通过严格的接口控制。
封装最主要的功能在于我们能修改自己的实现代码,而不用修改那些调用我们代码的程序片段。
适当的封装可以让程式码更容易理解与维护,也加强了代码数据的安全性。

比如一个这样的例子,人在银行的财产只能通过一些方法改变,例如存钱和取钱,如果按照普通的定义:

class person_bank:
    def __init__(self,name):
        self.money=0

p1=person_bank('lee')
p1.money=100
print(p1.money)
# 100

这样其实是不安全的,因为外部谁都可以自由的修改money的值

 这里引入私有属性的概念,其实就是使得外部不能访问,但是在类里面是可以访问的,只需要在变量前加 __

class person_bank:
    def __init__(self,name):
        self.__money=0
    def get_money(self,num):
        self.__money=self.__money+num
    def check(self):
        print(self.__money)
p1=person_bank('lee')
p1.check()
p1.get_money(100)
p1.check()
# 0
# 100

那么将私有属性放入类方法中修改的这种模式就叫做封装

当然方法也可以变为私有方法

class person_bank:
    def __init__(self,name):
        self.__money=0
    def __interest(self):
        self.__money=self.__money+1
p1=person_bank('lee')
p1.__interest()
# 'person_bank' object has no attribute '__interest'

但是其实私有属性和方法也不是完全不能外部访问的,也可以用下面这种方法破解

也就是  实例名._类名+方法名

print(p1._person_bank__money)
p1._person_bank__interest()

三大特征----多态

有时一个对象会有多种表现形式,比如网站页面有个button按钮,这个button的设计可以不一样(单选框、多选框、圆角的点击按钮、直角的点击按钮等),尽管长的不一样,但它们都有一个共同调用方式,就是onClick()方法。我们直要在页面上一点击就会触发这个方法。点完后有的按钮会变成选中状态、有的会提交表单、有的甚至会弹窗。这种多个对象共用同一个接口,又表现的形态不一样的现象,就叫做多态( Polymorphism )。

通过统一接口实现多态:

其实就是封装一个函数,调用不同类的同名方法

class one:
    def test(self):
        print(1)

class two:
    def test(self):
        print(2)

def gettest(obj):
    obj.test()

a=one()
b=two()
gettest(a)
gettest(b)

通过抽象类实现多态

class num:
    def test(self):
        # 可以继承,但是必须自己定义一个新的
        raise NotImplementedError('自己定义')


class one(num):
    def test(self):
        print(1)

class two(num):
    def test(self):
        print(2)

a=one()
b=two()
objs=[a,b]

for i in objs:
    i.test()

isinstance 

用于判断传入对象是否是指定的类型

class father():
    pass

class son(father):
    pass

a = son()
print(isinstance(a,father))
print(isinstance(a,son))
# True
# True

一些其他的方法无法做到判断父类,例如

print(type(a)==son)
print(type(a)==father)
print(type(a) is son)
print(type(a) is father)
# True
# False
# True
# False

 ==是对值的判断,is是对地址的判断,无法判断父类

抽象基类@abstractmethod

**抽象方法(Abstract Methods)**:抽象基类定义了一组抽象方法,这些方法在基类中没有实现任何功能,只有方法签名(名称和参数),通常使用`@abstractmethod`装饰器来标记这些方法。子类必须实现这些抽象方法。

from abc import ABC, abstractmethod
class Cache(ABC):
    @abstractmethod
    def get_cache(self):
        pass
    @abstractmethod
    def set_cache(self):
        pass

class get_cache(Cache):
    pass

class read_cache(Cache):
    def get_cache(self):
        print(1)
    def set_cache(self):
        print(2)

a = get_cache()
# TypeError: Can't instantiate abstract class get_cache with abstract methods get_cache, set_cache
b = read_cache()
b.get_cache()
# 1

例如上面这个例子,Cache就是抽象基类,他的子类必须重构 get_cache和 set_cache这两个方法才能被实例化文章来源地址https://www.toymoban.com/news/detail-686616.html

到了这里,关于Python面向对象编程(一)类的基础,关系,继承,封装,多态的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Python-面向对象:面向对象、成员方法 、类和对象、构造方法、魔术方法、封装、继承、类型注解、多态(抽象类(接口))

    当前版本号[20230806]。 版本 修改说明 20230806 初版 生活中数据的组织 学校开学,要求学生填写自己的基础信息,一人发一张白纸,让学生自己填, 易出现内容混乱 但当改为登记表,打印出来让学生自行填写, 就会整洁明了 程序中数据的组织 在程序中简单使用变量来记录学

    2024年02月14日
    浏览(36)
  • c、c++、java、python、js对比【面向对象、过程;解释、编译语言;封装、继承、多态】

    目录 内存管理、适用 区别 C 手动内存管理:C语言没有内置的安全检查机制,容易出现内存泄漏、缓冲区溢出等安全问题。 适用于系统级编程 C++ 手动内存管理:C++需要程序员手动管理内存,包括分配和释放内存,这可能导致内存泄漏和指针错误。 适用于游戏引擎和系统级编

    2024年02月08日
    浏览(57)
  • 面向对象详解,面向对象的三大特征:封装、继承、多态

    一、面向对象与面向过程 面向对象编程 (Object-Oriented Programming,简称OOP)和 面向过程编程 (Procedural Programming,简称PP)是两种不同的 编程范式 。 面向对象编程强调把问题分解成对象,通过封装、继承和多态等机制,来处理对象之间的关系 。每个对象都可以独立地处理自

    2024年02月21日
    浏览(37)
  • 头歌Educoder实验:C++ 面向对象 - 类的继承与派生

    第1关:公有继承 —— 学生信息类 任务描述 本关任务:采用公有继承设计学生信息类。 相关知识 继承 继承是使代码可以复用的重要手段,也是面向对象程序设计的核心思想之一。简单的说,继承是指一个对象直接使用另一对象的属性和方法。 C++ 中的继承关系就好比现实生

    2024年02月04日
    浏览(104)
  • 面向对象(类/继承/封装/多态)详解

    面向对象编程(Object-Oriented Programming,OOP)是一种广泛应用于软件开发的编程范式。它基于一系列核心概念,包括类、继承、封装和多态。在这篇详细的解释中,我们将探讨这些概念,并说明它们如何在PHP等编程语言中实现。 类是OOP的基础。它是一种用于创建对象的蓝图或模

    2024年02月08日
    浏览(45)
  • Java面向对象 - 封装、继承和多态

    目录 第1关:什么是封装,如何使用封装 第2关:什么是继承,怎样使用继承 第3关:super的使用 第4关:方法的重写与重载 第5关:抽象类 第6关:final的理解与使用 第7关:接口 第8关:什么是多态,怎么使用多态 Java_Educoder

    2024年02月07日
    浏览(60)
  • c++面向对象之封装、继承、和多态

    把客观事物封装成类,而且可以把自己的数据和方法设置为只能让可信的类或者对象操作,对不可信的信息进行隐藏(利用public,private,protected,friend)实现 has-a :描述一个类由多个部件类构成,一个类的成员属性是另一个已经定义好的类。 use-a:一个类使用另一个类,通过类之间

    2024年02月02日
    浏览(34)
  • 什么是面向对象,它的三个基本特征:封装、继承、多态

    什么是面向对象思想?已经学完了java确不知道如何跟别人解释面向对象是什么意思这很常见。让我们一起来回顾下这个奇思妙想~ 现在越来越多的高级语言流行起来了,如大家耳熟能详的c++,python,java等,这些都是基于 面向对象 的语言 而最最基础的,学校必学的语言----c语

    2024年02月02日
    浏览(38)
  • 【Java SE语法篇】8.面向对象三大特征——封装、继承和多态

    📚博客主页:爱敲代码的小杨. ✨专栏:《Java SE语法》 ❤️感谢大家点赞👍🏻收藏⭐评论✍🏻,您的三连就是我持续更新的动力❤️ 面向对象三大特性:封装、继承和多态。 在面向对象程式设计方法中,封装(英语:Encapsulation)是指一种将抽象性函式接口的实现细节部

    2024年02月01日
    浏览(44)
  • 软考:软件工程:面向对象技术与UML,时序图,用例图,类对象,封装,继承,多态

    提示:系列被面试官问的问题,我自己当时不会,所以下来自己复盘一下,认真学习和总结,以应对未来更多的可能性 关于互联网大厂的笔试面试,都是需要细心准备的 (1)自己的科研经历, 科研内容 ,学习的相关领域知识,要熟悉熟透了 (2)自己的实习经历,做了 什

    2024年02月11日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包