IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Python知识库 -> Python面向对象编程 -> 正文阅读

[Python知识库]Python面向对象编程

类与对象

类(Class): 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法,对象是类的实例。

类的三要素:类名、属性、方法

类名:大驼峰命名法每个单词首字母大写,无下划线

属性和方法的确定:
对对象的特征描述通常可以定义成属性
对象具有的行为通常可以定义成方法
面向对象三大特性:

封装:根据职责将属性和方法封装到一个抽象的 类 中
继承:实现代码的重用,相同的代码不需要重复的编写
多态:不同的对象调用相同的方法,产生不同的执行结果,增加代码的灵活度

定义简单类

创建只包含对象的方法

class 类名:
    def 方法1(self,参数列表):
        pass
    def 方法2(self,参数列表):
        pass
#类名大驼峰
#方法与函数定义方法一致,只是第一个参数为self

创建对象

对象变量=类名()
`dir` 内置函数返回对象的方法

方法中的self参数

在python中给对象设置属性,非常的容易,但是不推荐使用
(不修改类,直接给类增加一个属性)
对象名.属性=属性值
#只会给当前对象增加属性值
class Animal:

    def eat(self):
        print("吃饭")

    def run(self):
        print("跑步")
xx = Animal()
xx.name = "Tom"
ss = Animal()
print(xx.name)#返回Tom
print(ss.name)#报错
哪一个对象调用的方法,self就是哪一个对象的引用(在内存中的地址相同)
在类封装的方法内部,self 就表示当前调用方法的对象自己

调用方法时,程序员不需要传递 self 参数
在方法内部
	可以通过 self. 访问对象的属性
	也可以通过 self. 调用其他的对象方法

初始化方法

当使用 类名() 创建对象时,会自动执行以下操作:
1.为对象在内存中 分配空间 —— 创建对象
2.为对象的属性 设置初始值 —— 初始化方法(init)
这个初始化方法 就是 __init__ 方法,__init__ 是对象的内置方法
__init__ 方法是专用来定义一个类 具有哪些属性的方法!

如:
class Cat:
    def __init__(self):
        print("这是一个初始化方法")
tom = Cat()
>>>这是一个初始化方法

创建对象时会自动调用__init__方法

在初始化方法内部定义属性

在 __init__ 方法内部使用 self.属性名 = 属性的初始值 就可以 定义属性
定义属性之后,再使用 Cat 类创建的对象,都会拥有该属性

如:
class Cat:
    def __init__(self):
        self.name="Tom"
tom = Cat()
print(tom.name)
>>>Tom

改造初始化方法 —— 初始化的同时设置初始值

在开发中,如果希望在 创建对象的同时,就设置对象的属性,可以对 __init__ 方法进行 改造
1.把希望设置的属性值,定义成 __init__ 方法的参数
2.在方法内部使用 self.属性 = 形参 接收外部传递的参数
3.在创建对象时,使用 类名(属性1, 属性2...) 调用
如:
class Cat:
    def __init__(self,new_name):
        self.name = new_name

    def eat(self):
        print("%s爱吃鱼" % self.name)

tom = Cat("Tom")
lazy_cat=Cat("lazy_cat")
tom.eat()
lazy_cat.eat()


内置方法和属性

__del__ 方法:对象被从内存中销毁前,会被自动调用
__str__ 方法:返回对象的描述信息,print 函数输出使用

__del__ 方法

在 Python 中
当使用 类名() 创建对象时,为对象 分配完空间后,自动调用 __init__ 方法
当一个对象被从内存中销毁前,会自动调用 __del__ 方法

应用场景:
__init__ 改造初始化方法,可以让创建对象更加灵活
__del__ 如果希望在对象被销毁前,再做一些事情,可以考虑一下 __del__ 方法

生命周期:
一个对象从调用 类名() 创建,生命周期开始
一个对象的 __del__ 方法一旦被调用,生命周期结束
在对象的生命周期内,可以访问对象属性,或者让对象调用方法

如:
class Cat:
    def __init__(self,new_name):
        self.name=new_name
        print("%s来了"%self.name)
    def __del__(self):
        print("%s我去了"%self.name)

tom=Cat("tom")
print(tom.name)

print("-"*50)
>>>
tom来了
tom
--------------------------------------------------
tom我去了
#在分割线下方输出tom我去了,tom为全局变量,全部执行完成之后才能将tom回收

#可使用del tom对象 这样能提前回收tom

__str__ 方法

在 Python 中,使用 print 输出对象变量,默认情况下,会输出这个变量引用的对象是由哪一个类创建的对象,以及在内存中的地址(十六进制表示)

如果在开发中,希望使用print输出对象变量时,能够打印自定义的内容(不输出类和地址等信息),就可以利用 __str__ 这个内置方法了
注意:__str__ 方法必须返回一个字符串
如:
class Cat:
    def __init__(self,new_name):
        self.name=new_name
        print("%s来了"%self.name)

    def __del__(self):
        print("%s我去了"%self.name)

    def __str__(self):
        return "我是小猫[%s]"%self.name


tom=Cat("tom")
print(tom)
>>>
tom来了
我是小猫[tom]
tom我去了

封装

封装根据 职责将 属性和 方法封装到一个抽象的 类 中

案例一

1.封装是面向对象编程的一大特点
2.面向对象编程的第一步 —— 将 属性和方法 封装到一个抽象的类中
3.外界使用类创建对象然后让对象调用方法
4.对象方法的细节都被封装在类的内部

如:
class Person:
    def __init__(self,name,weight):
        self.name=name
        self.weight=weight

    def __str__(self):
        return "我的名字叫 %s 体重是 %.2f 公斤"%(self.name,self.weight)

    def run(self):
        print("%s爱跑步,跑步锻炼身体"%self.name)
        self.weight-=0.5

    def eat(self):
        print("%s是吃货,吃完再减肥"%self.name)
        self.weight+=0.6

x=Person("xiao ming",65.3)
x.run()
x.eat()
print(x)

>>>
xiao ming爱跑步,跑步锻炼身体
xiao ming是吃货,吃完再减肥
我的名字叫 xiao ming 体重是 65.40 公斤`

案例二

在这里插入图片描述
image-20221014101454124

class HouseItem:
    def __init__(self,name,area):
        self.name=name
        self.area=area

    def __str__(self):
        return "[%s]占地%.2f"%(self.name,self.area)


class House:
    def __init__(self,house_type,area):#需要外地传递的参数才需要定义成初始化形参
        self.house_type=house_type
        self.area=area
        self.free_area=area#剩余面基
        self.item_list=[]#家具列表

    def __str__(self):
        return "户型:%s\n总面积:%.2f[剩余:%.2f]\n家具:%s"%(self.house_type,self.area,self.free_area,self.item_list)

    def add_item(self,item):
        print("要添加%s"%item)
        #判断家具的面积
        #将家具添加到列表(判断剩余面积是否满足条件)
        #计算剩余面积
        if item.area>self.free_area:
            print("%s面积太大,无法添加"%item.name)
            return
        self.item_list.append(item.name)
        self.free_area-=item.area

#创建家具对象
bed=HouseItem("席梦思",4)
chest=HouseItem("衣柜",2)
table=HouseItem("餐桌",1.5)
print(bed,chest,table,sep="\n")

#创建房子对象
my_house=House("两室一厅",60)
#添加家具
my_house.add_item(bed)
my_house.add_item(chest)
my_house.add_item(table)
print(my_house)

案例三

一个对象的 属性可以是 另外一个类创建的对象

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4EINvSC0-1665753279837)(C:\Users\98306\AppData\Roaming\Typora\typora-user-images\image-20221014102638240.png)]

class Gun:
    def __init__(self, model):
        self.model = model
        self.bullet_count = 0

    def add_bullet(self, count):
        self.bullet_count += count

    def shoot(self):
        if self.bullet_count<=0:
            print("[%s]没有子弹了...." % self.model)
            return
        self.bullet_count -= 1
        print("Peng![%s]发射了一枚子弹" % self.model)


class Soldier:
    def __init__(self,name):
        self.name=name
        self.gun=None#新兵没有枪

    def fire(self):
        if self.gun is None:
            print("士兵[%s]没枪"%self.name)
            return
        print("[%s]冲锋"%self.name)
        self.gun.add_bullet(50)
        self.gun.shoot()

ak47=Gun("ak47")
xusanduo=Soldier("xusanduo")
xusanduo.gun=ak47
xusanduo.fire()
print(xusanduo.gun)
>>>
[xusanduo]冲锋
Peng![ak47]发射了一枚子弹
<__main__.Gun object at 0x000001C069E90408>

身份运算符

身份运算符用于比较两个对象的内存地址是否一致 —— 是否是对同一个对象的引用

在Python中针对None比较时,建议使用is判断
is:is 是判断两个标识符是不是引用同一个对象x is y,类似 id(x) == id(y)
is not:is not 是判断两个标识符是不是引用不同对象	x is not y,类似 id(a) != id(b)

私有属性和私有方法

应用场景及定义方式

应用场景:
在实际开发中,对象的某些属性或方法 可能只希望在对象的内部被使用,而不希望在外部被访问到
	私有属性就是对象不希望公开的属性
	私有方法就是对象不希望公开的方法

定义方式:
在定属性或方法时,在属性名或者方法名前增加两个下划线定义的就是 私有属性或方法

伪私有属性和私有方法(科普)

提示:在日常开发中,不要使用这种方式访问对象的 私有属性 或 私有方法

Python 中,并没有 真正意义私有

  • 在给 属性、方法 命名时,实际是对 名称 做了一些特殊处理,使得外界无法访问到
  • 处理方式:在 名称 前面加上 _类名 => _类名__名称

python中没有真正意义上的私有,可以通过 对象._类名.__名称来访问私有方法和私有属性

继承

继承 实现代码的重用,相同的代码不需要重复的编写

单继承

子类拥有 父类 的所有 方法和 属性

继承的概念、语法和特点

在这里插入图片描述

继承的语法

class 类名(父类名):

    pass
子类继承自父类,可以直接享受父类中已经封装好的方法,不需要再次开发

子类中应该根据职责,封装子类特有的属性和方法
Dog类是Animal类的子类,Animal类是Dog类的父类,Dog类从Animal类继承

Dog类是Animal类的派生类,Animal类是Dog类的基类,Dog类从Animal类派生
继承的传递性:
C类从B类继承,B类又从A类继承
那么C类就具有B类和A类的所有属性和方法
子类拥有父类以及父类的父类中封装的所有属性和法
class Animal:
    def eat(self):
        print("吃")

    def drink(self):
        print("喝")

    def run(self):
        print("跑")

    def sleep(self):
        print("睡")


class Dog(Animal):  # Dog类继承Animal类,子类只需要封装自己独有的属性和方法即可
    def bark(self):
        print("汪汪叫")


class xiaotianquan(Dog):  # 继承的传递性
    pass


# 子类拥有父类所有的属性和方法
wangcai = xiaotianquan()
wangcai.eat()
wangcai.drink()
wangcai.run()
wangcai.sleep()
wangcai.bark()

方法的重写

子类拥有父类的所有方法和属性

子类继承自父类,可以直接享受父类中已经封装好的方法,不需要再次开发

当 父类 的方法实现不能满足子类需求时,可以对方法进行 重写(override)
在这里插入图片描述

重写父类方法有两种情况:

1. 覆盖父类的方法
2. 对父类方法进行 扩展

覆盖父类的方法

如果在开发中,父类的方法实现和子类的方法实现,完全不同
就可以使用覆盖的方式,在子类中重新编写父类的方法实现

具体的实现方式,就相当于在 子类中定义了一个和父类同名的方法并且实现

重写之后,在运行时,只会调用子类中重写的方法,而不再会调用父类封装的方法

对父类方法进行 扩展

如果在开发中,子类的方法实现中包含父类的方法实现
父类原本封装的方法实现是子类方法的一部分
就可以使用扩展的方式
1.在子类中重写父类的方法
2.在需要的位置使用  super().父类方法  来调用父类方法的执行
3.代码其他的位置针对子类的需求,编写子类特有的代码实现

关于 super

在 Python中 super 是一个 特殊的类
super() 就是使用 super 类创建出来的对象
最常 使用的场景就是在 重写父类方法时,调用 在父类中封装的方法实现

调用父类方法的另外一种方式(知道)
在 Python 2.x 时,如果需要调用父类的方法,还可以使用以下方式:

父类名.方法(self)

这种方式,目前在 Python 3.x 还支持这种方式
这种方法 不推荐使用,因为一旦 父类发生变化,方法调用位置的 类名 同样需要修改

提示
在开发时,父类名 和 super() 两种方式不要混用
如果使用 当前子类名 调用方法,会形成递归调用,出现死循环

父类的私有属性和私有方法

1.子类对象不能在自己的方法内部,直接访问父类的 私有属性或私有方法
2.子类对象可以通过父类的公有方法间接访问到私有属性或私有方法
	私有属性、方法是对象的隐私,不对外公开,外界以及子类都不能直接访问
	私有属性、方法 通常用于做一些内部的事情

在这里插入图片描述

B的对象不能直接访问 __num2 属性
B的对象不能在demo方法内访问 __num2 属性
B的对象可以在demo方法内,调用父类的test方法
父类的test方法内部,能够访问 __num2 属性和 __test 方法

多继承

子类可以拥有 多个父类,并且具有 所有父类 的 属性 和 方法

在这里插入图片描述

class 子类名(父类名1, 父类名2...)
    pass

多继承的使用注意事项

问题的提出

如果不同的父类中存在同名的方法,子类对象在调用方法时,会调用哪一个父类中的方法呢?
提示:
开发时,应该尽量避免这种容易产生混淆的情况! 
—— 如果父类之间存在 同名的属性或者方法,应该尽量避免使用多继承

在这里插入图片描述

多态

多态 不同的 子类对象调用相同的 父类方法,产生不同的执行结果

多态可以增加代码的灵活度
以继承和重写父类方法为前提
是调用方法的技巧,不会影响到类的内部设计

在这里插入图片描述

案例

需求:
在Dog类中封装方法game
	普通狗只是简单的玩耍
定义XiaoTianDog继承自Dog,并且重写game方法
	哮天犬需要在天上玩耍
定义Person类,并且封装一个和狗玩的方法
	在方法内部,直接让狗对象调用game方法

在这里插入图片描述

Person类中只需要让狗对象调用game方法,而不关心具体是什么狗
game方法是在Dog父类中定义的
在程序执行时,传入不同的狗对象实参,就会产生不同的执行效果

多态 更容易编写出出通用的代码,做出通用的编程,以适应需求的不断变化!

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

    def game(self):
        print("%s蹦蹦跳跳的玩耍"%self.name)


class XiaoTianQuan(Dog):
    def game(self):
        print("%s飞到天上去玩耍"%self.name)


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

    def game_with_dog(self,dog):
        print("%s和%s一起玩"%(self.name,dog.name))
        dog.game()

dahuang=Dog("大黄")
wangcai=XiaoTianQuan("神*旺财")
xiaoming=Person("小明")
xiaoming.game_with_dog(wangcai)
xiaoming.game_with_dog(dahuang)
>>>
小明和神*旺财一起玩
神*旺财飞到天上去玩耍
小明和大黄一起玩
大黄蹦蹦跳跳的玩耍
#传入不同的对象会产生不同的结果,这个就是多态

!**

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

    def game(self):
        print("%s蹦蹦跳跳的玩耍"%self.name)


class XiaoTianQuan(Dog):
    def game(self):
        print("%s飞到天上去玩耍"%self.name)


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

    def game_with_dog(self,dog):
        print("%s和%s一起玩"%(self.name,dog.name))
        dog.game()

dahuang=Dog("大黄")
wangcai=XiaoTianQuan("神*旺财")
xiaoming=Person("小明")
xiaoming.game_with_dog(wangcai)
xiaoming.game_with_dog(dahuang)
>>>
小明和神*旺财一起玩
神*旺财飞到天上去玩耍
小明和大黄一起玩
大黄蹦蹦跳跳的玩耍
#传入不同的对象会产生不同的结果,这个就是多态
  Python知识库 最新文章
Python中String模块
【Python】 14-CVS文件操作
python的panda库读写文件
使用Nordic的nrf52840实现蓝牙DFU过程
【Python学习记录】numpy数组用法整理
Python学习笔记
python字符串和列表
python如何从txt文件中解析出有效的数据
Python编程从入门到实践自学/3.1-3.2
python变量
上一篇文章      下一篇文章      查看所有文章
加:2022-10-17 12:28:59  更:2022-10-17 12:31:02 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/26 1:24:34-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计