2000字范文,分享全网优秀范文,学习好帮手!
2000字范文 > Python高级编程1-python面向对象初识

Python高级编程1-python面向对象初识

时间:2021-03-15 12:57:19

相关推荐

Python高级编程1-python面向对象初识

面向对象初识

文章目录

一、面向对象(一)什么是面向对象?(二)什么是类?(三)使用面向对象写代码的好处(四)面向对象的三大特征1. 封装小案例:使用面向对象思想实现游戏中攻击、血量等功能 2.继承与多态

一、面向对象

(一)什么是面向对象?

​ 面向对象是一个编程范式(也就是我们写代码的套路)

​ 满足我们的需求,比如:我现在给你一个商品列表,要你按照价格排序

首先我们要现有一个商品表

commodity_infos = [{"cid":101,"name":"苹果","price":5},{"cid":102,"name":"葡萄","price":8},{"cid":103,"name":"橘子","price":3},{"cid":104,"name":"猕猴桃","price":6},{"cid":105,"name":"柚子","price":2}]

输出商品信息:利用一个for循环便可以将商品的信息输出

for commodity_info in commodity_infos:print(commodity_info)

我们的需求是:通过价格排序

思路:

1.确定列表里的第一个元素的价格是列表里面最大的

拿列表里的第一个元素和它后边的元素比较一下

如果发现比第一个元素大的就要交换元素的位置

那么我们如何交换位置嘞?

list1 = [1, 2, 3, 4, 5]list1[1], list1[0] = list1[0], list1[1]#运行结果:[2, 1, 3, 4, 5]#回顾一点点知识:给列表里的值重新赋值给变量a, b, c, d, e = list1print(a)#运行结果:2

2.确定列表里的第二个元素的价格是列表里面第二大的

拿列表里的第二个元素和它后边的元素比较一下

如果发现比第二个元素大的就要交换元素的位置

3.确定列表里的第三个元素的价格是列表里面第三大的

拿列表里的第三个元素和它后边的元素比较一下

如果发现比第三个元素大的就要交换元素的位置

4.确定列表里的第四个元素的价格是列表里面第四大的

拿列表里的第四个元素和它后边的元素比较一下

如果发现比第四个元素大的就要交换元素的位置

(第五个就不用啦,因为我们在第四步的时候就已经将整体的排序都做好了)

实现的步骤:

1.取出前几个数据(不要最后一个)

2.拿到数据与后边的元素作比较

3.发现更大的交换位置

commodity_infos = [{"cid": 101, "name": "苹果", "price": 5},{"cid": 102, "name": "葡萄", "price": 8},{"cid": 103, "name": "橘子", "price": 3},{"cid": 104, "name": "猕猴桃", "price": 6},{"cid": 105, "name": "柚子", "price": 2}]#1.取出前几个数据(不要最后一个)for r in range(len(commodity_infos) - 1): # r表示第r个数据for c in range(r + 1, len(commodity_infos)):# c表示r后边的数据#2.拿到数据与后边的元素作比较if commodity_infos[r]["price"] < commodity_infos[c]["price"]:#3.发现更大的交换位置commodity_infos[r], commodity_infos[c] = commodity_infos[c], commodity_infos[r]for commodity_info in commodity_infos:print(commodity_info)

面向过程

总结之前写代码的套路,即分析出来写代码的步骤,然后使用代码逐步实现,如上诉的例子👆。这就是面向过程(面向:即是以什么为核心)

面向过程就是把 一个复杂的过程流程化,进而简单化,我们要实现一个功能就要使用这种思维方式。

面向对象:对象再我们程序里边叫object,有物体的意思。

在使用面向对象写代码的时候,首先要想的就是这个程序有哪些部分组成,然后再去想每一步要怎么做。

在面向对象里面,我们想要把现实的事物在我们程序里面表示,需要将现实的事物抽象成我们代码里边的类,然后通过类产生程序对象,通过对象和我们现实生活中的事物对应。

面向对象与面向过程的关系

​ 面向对象和面向过程都是我们写代码的方式,不能把他们对立起来,他们之间是相辅相成的。面向对象是从整体上分析构成,面向过程是注重怎样实现。

小tips❤️:

1.输出快捷方式

​ 用法:变量名称.print + 按下enter键 即可立即变成 print(变量名称) 的形式

2.快速打出for循环的模板

​ 用法:iter + 按下enter键 即可立即出现一个for循环的模板,如下

for in :

3.快速调整代码的的格式:Ctrl+Alt+L

4.快速注释:Ctrl+/

5.property的快捷模板:

​ 用法: props + Enter 即可出现模板

@propertydef (self):return @.setter

6.快速将参数传递的快捷键Alt+Enter+Enter,效果如下:

class Commodity :def __init__(self,cid,name,price):self.price = priceself.name = nameself.cid = cid

(二)什么是类?

​ 就是我们生活当中类别的意思

语法:

class类的名称:

1.先定义类

使用class关键字去定义一个类

类名建议使用驼峰体

类与类之间主要是行为不同:人类和动物类有不同的行为

在类中写的函数,我们管它叫做方法,每个方法都会有一个self参数

#1.先定义类class GirlFriend:def send_msg(self): #女朋友会给男朋友发消息print('给男朋友发消息')def shopping(self): #女朋友会购物print('买买买')

2.产生对象

类名+()就是实列话一次,实例化一次就是得到一个对象。实例化两次就得到两个对象。

g1 = GirlFriend()g2 = GirlFriend()

但是每个女朋友都有她独特的地方,我们这时候就会用到一个叫做__init__的方法

当我们添加了__init__方法的时候,首先会根据这个类创建一个对象,第二部接着去执行__init__这个方法,python会自动将创建的对象当成参数传值给self(self就是对象的一个内存空间)\

举个🌰:如下,创建对象时,因为有init,所以会将g1传递给self。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2PrrUPVP-1651233023580)(C:\Users\彭兴娇\AppData\Roaming\Typora\typora-user-images\1645447697005.png)]

class GirlFriend:def __init__(self,name,face_score,money,boy_fiend):#实列属性:属于对象的,只能通过对象调用self.name = nameself.face_score = face_scoreself.money = moneyself.boy_fiend = boy_fiend#绑定到对象的方法:可以使用类或者对象调用#如果我们使用类来调用的话,这个方法就是一个普通的函数#如果是对象来调用的话,就会把对象当成第一个参数传递def send_msg(self): #女朋友会给男朋友发消息print('给男朋友发消息')def shopping(self): #女朋友会购物print('买买买')g1 = GirlFriend("小红",95,88888,"小蓝")g2 = GirlFriend()#如果我们想要输出女朋友的名字或者颜值,我们可以像这样子输出:print(g1.name)print(g1.face_score)#如果我们是通过类来调用print(GirlFriend.send_msg) #这样字就只是一个普通的函数#如果我们想要调用的话,就必须传入参数GirlFriend.send_msg

我们在给对象传值得时候会自己传到参数里边去。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1MKER7uw-1651233023582)(C:\Users\彭兴娇\AppData\Roaming\Typora\typora-user-images\1644586886286.png)]

(三)使用面向对象写代码的好处

好处:把数据对象封装到一个类里边去,然后在方法里边对已经封装的数据进行操作,这样可以将数据对数据的操作相关联,让代码的可读性更高,让我们分析问题的时候更方便。

#如果我们将每一个商品做成一个类class Commodity :def __init__(self,cid,name,price):self.price = priceself.name = nameself.cid = cid#定义一个功能,用于输出商品的信息def print_commodity_info(self):print(f"编号:{self.cid}--商品名称:{self.name}--商品价格:{self.price}")#如何去产生一个真实的商品呢?我们使用类名往里边传入参数,就产生了一个商品commodity_info = [#商品对象Commodity(1001,"苹果",5)]

(四)面向对象的三大特征

1. 封装

将多个数据打包、封装到一个自定义的类里面,对类外提供必要的功能隐藏实现的细节。

好处:

将多个数据打包、封装到一个自定义的类里面

符合人的思维方式

可以将数据和对数据的操作封装在一起,有利于我们分析解决问题

以后我们拿到一个需求,我们应该将这个需求分解成多个类,类和类之间是行为上的不同,对象和对象之间是数据上的不同。

例如:五子棋可以分为:棋子,棋盘,规则三个类

便于分工代码可读性更高可扩展性强

对类外提供必要的功能隐藏实现的细节,无关紧要的不对外提供

我写了一个类在我们使用的时候,不需要考虑每个功能是怎么实现的

class Atm:#以下这五个功能,我们在使用的时候不用考虑细节,是怎么来的def card(self):print("插卡")def auth(self):print("用户认证")def input(self):print("输入取款的金额")def print_bill(self):print("打印账单")def take_money(self):print("取款")#我们只需要给出一个功能来触发上述五个功能即可def draw_money(self):self.cardself.authself.inputself.print_billself.take_moneya = Atma.draw_money()#运行结果:#插卡#用户认证#输入取款金额#打印账单#取款a.card()#在这一步我们发现card等功能还是暴露出来了,给用户看到了,我们需要将这些隐藏起来不给用户看到

python中我们实现隐藏是通过私有化来做的,在命名的时候使用双下划线开头,就代表我们要把这个功能藏起来

#如何实现隐藏class A:def __init__(self,name):self.__name = name #在前边使用双下划线,代表把name隐藏了,私有化了def __foo(self):#方法也是可以隐藏的print('foo')a = A("孜孜淑淑")print(a.name) #此时是访问不到name的,因为name已经被隐藏了,执行会报错print(A.__dict__)#通过这种方式,我们就可以知道类里边有哪些东西,隐藏的也能看到#如何访问隐藏的方法A._A__fool(1)#通过该方法就可以访问隐藏的方法或者变量#特点:'''1.在类外我们不是直接通过 对象.属性/方法 访问2.在类的内部是可以直接使用的'''

隐藏的使用场景:

​ 实列属性:我们把放在____init____里边的叫做实列属性,也就是每个对象属性

​ 使用场景:

class GirlFriend:def __init__(self,name,age,weight):self.weight = weightself.__age = ageself.__name = nameself.set_age(age)def get_age(self):return self.__agedef set_age(self,value): #限定女朋友的年龄if 21 <= value <=30:set.__age = valueelse:raise ValueError("我不要") #如果没有达到年龄的要求,就直接报错。这样可以保证数据的安全,比如空调的温度#实例化就是通过调用一次类名,就进行实例化一次g1 = GirlFriend("小红",18,100)

公开的实例属性,缺少逻辑验证。私有实例和两个公开的方法结合使用。在这里我们介绍一个类property:

'''使用了property(放在类里边的)之后,我们在通过 对象.age 就会触发到 get_age的执行当我们使用 对象.age = 赋值 的时候就会出发到 set.ageproperty对象可以当作是拦截了我们对age的读写操作,优先级更高'''#property使用方法一:class GirlFriend:def __init__(self,name,age,weight):self.weight = weightself.__age = ageself.__name = nameself.set_age(age)def get_age(self):return self.__agedef set_age(self,value): #限定女朋友的年龄if 21 <= value <=30:set.__age = valueelse:raise ValueError("我不要") age = property(get_age,set_age) #会使优先级更高,当涉及到age时,会先找到get_age,set_age这两个方法#property使用方法二:class GirlFriend:def __init__(self,name,age,weight):self.weight = weightself.__age = ageself.__name = nameself.set_age(age)@property #相当于执行了 age = property(age) 创建了一个property对象 只负责拦截读取操作def age(self):return self.__age@age.setter #拦截我们写入的操作def age(self,value): #限定女朋友的年龄if 21 <= value <=30:set.__age = valueelse:raise ValueError("我不要") '''使用该方法的快捷方式:`props`+`Enter` 就会自动创建一个该模板@propertydef (self):return @.setter'''

小案例:使用面向对象思想实现游戏中攻击、血量等功能

使用面向对象思想实现以下两个要求:

玩家可以攻击敌人,敌人受伤血量减少的同时播放敌人受伤的画面

敌人也可以攻击玩家,玩家血量减少的同时出现碎屏效果

#玩家类class Player:def __init__(self,hp,atk): #每一个玩家都会有血量和攻击力self.atk = atkself.hp = hpdef attack(self,enemy):print('玩家攻击敌人')enemy.enemy_wounded(self.atk)def player_injured(self,value):print('碎屏 啊啊啊')self.hp -= value # 被攻击血量应该减少print(f'现在玩家的血量是{self.hp}')#敌人类class Enemy:def __init__(self,hp,atk):self.atk = atkself.hp = hpdef enemy_wounded(self,value): #value是减少的血量值print('播放受伤的画面')self.hp -= value #被攻击血量应该减少print(f'现在敌人的血量是{self.hp}')def attack(self,player):print('敌人攻击玩家')player.player_injured(self.atk)p1 = Player(500, 50) #创建一个玩家e1 = Enemy(100, 10) #创建一个敌人p1.attack(e1) #玩家攻击敌人print('-'*20)e1.attack(p1)#运行结果:'''玩家攻击敌人播放受伤的画面现在敌人的血量是50--------------------敌人攻击玩家碎屏 啊啊啊现在玩家的血量是490'''

在该案例当中添加“手雷”,手雷爆炸可以炸玩家也可以炸敌人

#手雷class Grenade:def __init__(self,atk): # atk攻击力self.atk = atkdef explode(self, target): #爆炸,target攻击目标print("拉环")print("手雷爆炸")'''if type(target) == Enemy:#如果攻击对象是敌人target.enem_wounded(self.atk) #敌人受伤elif type(target) == Player: #如果攻击的对象是玩家target.player_injured(self.atk) #玩家受伤'''#改良之后,我们就不用判断它是那种属性的人了,直接调用即可target.damage(self.atk)#分析:不管是我们的玩家还是敌人,总之有个共同属性,便是可攻击对象,在这里我们就可以创建以个攻击对象的父类class AttackTarget: #父类def damage(self,value): #定义一个方法,让他们被攻击pass#玩家类class Player(AttackTarget):def __init__(self,hp,atk): #每一个玩家都会有血量和攻击力self.atk = atkself.hp = hpdef attack(self,enemy):print('玩家攻击敌人')enemy.enemy_wounded(self.atk)def player_injured(self,value):print('碎屏 啊啊啊')self.hp -= value # 被攻击血量应该减少print(f'现在玩家的血量是{self.hp}')#敌人类class Enemy(AttackTarget):def __init__(self,hp,atk):self.atk = atkself.hp = hpdef enemy_wounded(self,value): #value是减少的血量值print('播放受伤的画面')self.hp -= value #被攻击血量应该减少print(f'现在敌人的血量是{self.hp}')def attack(self,player):print('敌人攻击玩家')player.player_injured(self.atk)

类属性

对象中有多个相同的数据,这个时候我们可以选择吧这个给数据做成类变量

举个例子:

class Person:#定义一个人的类country = "中国" #所有的人都是中国人,这个是相同的数据def __init__(self, name, age):self.name = nameself.age = agep1 = Person("小红",18)p2 = Person("小蓝",22)print(p1.name)print(p2.name)#country 是他们的共同属性,都可以用print(p1.country)print(p2.country)

2.继承与多态

(1)继承:重用类的功能和概念

​ ‘你要笑死我,然后继承我的花呗’ 父子的关系才会有继承

​ 比如皇位,江山不需要太子打,但太子可以登基

​ 在编程里,父类代码不用子类写,但是子类可以用父类的代码

# **********继承的写法***************# 父类:动物class Animal:def eat(self):print("吃")# 子类:狗的父类是动物class Dog:def eat(self):print("吃")def run(self):print("跑")# 子类:鸟的父类是动物class Bird:def eat(self):print("吃")def fly(self):print("飞")# 狗和鸟有共性,我们可以将他们的共性写在父类,这样鸟和狗都可以使用d1 = Dog()# 对象本身找,没有的话然后到类里边找,最后到父类里边找d1.eat = 123print(d1.eat)

小练习:

以下代码运行结果是什么?class Foo:def f1(self):print("from Foo.f1")def f2(self):print("from Foo.f2")self.f1()class Bar(Foo):def f1(self):print("from Bar.f1")b = Bar()b.f2()#运行结果:'''from Foo.f2from Bar.f1''''''原因:首先,b是一个没有实列属性的对象,b这个对象所在的类下边是没有f2这个属性,没有的话就去找父类Foo,那就打印出来from Foo.f2然后接下来是self.f1,在这里的这个self会在自己(b)的类里边找,就是Bar里边的f1'''

子类里边什么都没有的话,那这个子类里面的所有东西都是继承父类的

在子类里面定义了自己的,就以自己的为准

问题点是我们在子类里面派生出来的方法里面我想用父类的代码,不是说重新写一遍,我是想在父类的基础上做一点小改动,这个时候我们就需要在子类里边调用父类的方法。

#**********在子类里边调用父类的方法*************class Animal: #父类def __init__(self, name, sex, age):self.age = ageself.sex = sexself.name = namedef eat(self):print("吃")class Dog(Animal): #子类def __init__(self, name, sex, age, title):self.title = titleself.age = ageself.sex = sexself.name = named1 = Dog("旺财", "公", 3, "拉布拉多") #在这里,我们最先促发到的还是Dog里边的__init__print(d1.__dict__)#方式一:指名道姓class Dog(Animal): #子类def __init__(self, name, sex, age, title):Aniaml.__init__() #执行到此处默认调用父类的__init__self.title = title#方法二:super()方法'''使用super()会得到一个特殊的对象,这个对象专门用来调用父类的方法'''class Dog(Animal): #子类def __init__(self, name, sex, age, title):super().__init__(name, sex, age) #执行到此处调用父类的__init__self.title = title

(2)多态:父类的同一中行为在不同的子类上有不同的实现,可以增强我们程序的可扩展性。

增加新的东西不会影响到我们的类

#子类

definit(self, name, sex, age, title):

self.title = title

self.age = age

self.sex = sex

self.name = name

d1 = Dog(“旺财”, “公”, 3, “拉布拉多”) #在这里,我们最先促发到的还是Dog里边的__init__

print(d1.dict)

#方式一:指名道姓

class Dog(Animal): #子类

definit(self, name, sex, age, title):

Aniaml.init() #执行到此处默认调用父类的__init__

self.title = title

#方法二:super()方法

‘’’

使用super()会得到一个特殊的对象,这个对象专门用来调用父类的方法

‘’’

class Dog(Animal): #子类

definit(self, name, sex, age, title):

super().init(name, sex, age) #执行到此处调用父类的__init__

self.title = title

(2)多态:父类的同一中行为在不同的子类上有不同的实现,可以增强我们程序的可扩展性。增加新的东西不会影响到我们的类​

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。