目录
面向对象编程的特点:
封装:封装是将数据和操作(方法)封装在一个对象中的能力
继承:继承是指一个类(子类)可以继承另一个类(父类)的属性和方法。
我们为什么需要继承呢?
父类/基类 => ATM
子类/派生类=> ChinaATM/ICBCATM
ATM系统父类子类讲解代码:
经典类和新式类
经典类 和 新式类的区别:(python2的环境中进行)
区别一:查看数据类型之间的区别
区别二:多重继承的查找顺序不同
经典类和新式类的继承关系
经典类 => 深度优先算法
新式类 => C3算法
多态:多态是指同一种操作或方法可以在不同的对象上产生不同的行为。
多态示例:
静态方法和类方法:
示例代码:实例方法、静态方法、类方法的定义和使用
什么时候使用静态方法呢?
什么时候使用类方法呢?
调用静态、类、实例方法的条件:
python中下划线的使用:
python中的下划线:
单下划线开头的变量/函数/属性/方法/类--》保护对象 => 外部还是可以用
双下划线开头的变量/函数/属性/方法/类--》私有对象 => 只在自己空间中生效
示例:python中内置特殊变量或特殊方法一般都是用双下划线__开头双下划线结尾的
通过代码来实现单下划线 和 双下划线不同的功能
实验:回合制攻击游戏:
游戏介绍:
面向对象编程的特点:
封装(Encapsulation):封装是将数据和操作(方法)封装在一个对象中的能力。对象对外部提供一组公共接口(方法),通过这些接口可以访问和操作对象的内部状态,而对象的内部实现细节对外部是不可见的。封装提供了信息隐藏和保护数据的机制,使得对象的设计更加模块化、安全性更高。
继承(Inheritance):继承是指一个类(子类)可以继承另一个类(父类)的属性和方法。通过继承,子类可以重用父类的代码,并可以在此基础上添加、修改或覆盖父类的行为。继承提供了代码的重用性和层次化组织的能力,使得代码更加可维护和可扩展。
多态(Polymorphism):多态是指同一种操作或方法可以在不同的对象上产生不同的行为。多态通过继承和方法重写实现,允许使用父类类型的变量来引用子类对象,从而在运行时动态地调用子类的方法。多态提供了接口的灵活性和代码的可扩展性,使得程序更加具有通用性和可复用性。
抽象(Abstraction):抽象是指从具体的事物中提取出共同的特征和行为,形成抽象类或接口。抽象类定义了一组抽象方法和属性,描述了对象的基本行为和特征,而具体的实现则由子类来完成。抽象类和接口提供了对问题域的建模能力,使得程序设计更加符合现实世界的抽象和概念。
封装:封装是将数据和操作(方法)封装在一个对象中的能力
继承:继承是指一个类(子类)可以继承另一个类(父类)的属性和方法。
# 在python2中属于经典类
class A:
pass
# 在python2中属于经典类
class B():
pass
# 在python2中属于新式类
class C(object):
pass
# class 类名(父类列表): pass --》 我们可以继承的多个父类
# python3 以上写法效果一样的。
# python3 中默认继承自object
我们为什么需要继承呢?
因为继承可以帮助我们减少重复的代码
如下面的ATM系统为例(它可以使我们的扩展性更强)
# ATM类 bank =>银行
# 我们需要使用中国工商银行的ATM机和中国银行的ATM机
# 因此可以看到我们都需要使用ATM机的功能,只是我们需要去的银行不同,因此我们的父类可以使用ATM , 子类可以使用 ChinaATM/ICBCATM(中国银行 或者 中国工商银行)
父类/基类 => ATM
子类/派生类=> ChinaATM/ICBCATM
父类和子类的创建条件:
父类:所有子类都公共的功能
子类; 如果父类的功能并不能满足我们的需求,我们需要撰写子类重写该方法
如果父类没有该功能,我们需要撰写子类自己定义一个功能(也包括属性)
如果__init__初始化不满足需求,我们需要在子类中重写一个__init__,并也可以执行父类的__init__函数,使用super().__init__ 方法
多重继承:一个类可以继承多个父类
多级别的继承
ATM系统父类子类讲解代码:
其中包含了ATM(object), 子类ChinaATM(ATM)和ICBCATM(ATM))
使用到了继承的添加、修改 和 重写父类的行为
ChinaATM继承自ATM, 因此ATM中的所有东西,ChinaATM都有,并在其中添加 __init__ 初始化函数的功能,如果父类中有相同的变量,我们的ChinaATM内可以不用再继续定义了,我们只需要使用super().__init__(No, location, balance)去调用父类中的变量即可
重写属性、方法 => 父类的某些东西,不满足需求,可以重写
如果需要的功能,父类没有,自己添加一个
class ATM(object):
bank = "银行ATM"
def __init__(self, No, location, balance):
print("这是ATM的__init__")
self.No = No
self.location = location
self.balance = balance
def save_money(self, money):
self.balance += money
print(f"{self.bank}-{self.No}余额为:{self.balance}")
def get_money(self, money):
self.balance -= money
print(f"{self.bank}-{self.No}余额为:{self.balance}")
class ChinaATM(ATM):
bank = "中国银行ATM"
# No, location, balance, test
def __init__(self, No, location, balance, test):
print("这是ChinaATM的__init__")
self.test = test
super().__init__(No, location, balance)
# ChinaATM继承自ATM,ATM中的所有东西,ChinaATM都有
class ICBCATM(ATM):
# 重写属性、方法 => 父类的某些东西,不满足需求,可以重写
bank = "工商银行ATM"
def save_money(self):
print("这是ICBC-ATM的save_money")
# 如果需要的功能,父类没有,自己添加一个
def show(self):
print(self.bank, self.No)
# 创建一个中国银行的ATM机
china_atm1 = ChinaATM("cn_atm_001", "长沙市芙蓉区湖南农业大学", 100, "ok")
china_atm1.get_money(10)
print(china_atm1.bank)
# icbc_atm1 = ICBCATM("icbc_atm_001", "长沙市岳麓区",1000)
# icbc_atm1.save_money()
# icbc_atm1.show()
经典类和新式类
新式类:继承与object => python3中默认都是继承于object => python3中所有的类都是新式类哦
经典类: 没有显式地继承object(就是父类没有写object来表示自己是父类) =>python2中
经典类 和 新式类的区别:(python2的环境中进行)
区别一:查看数据类型之间的区别
#定义了四个类
class A():pass 经典类
class B: pass 经典类
class C(object):pass 新式类
class D(object):pass 新式类
# 区别一:查看数据类型之间的区别
# 经典类:
a = A() # type(a) => instance
b = B() # type(b) => instance
type(a) == type(b) => True # 上面的方式来判断数据类型是不对的
a.__class__ => #这种方式才能获取到正确的数据类型
b.__class__
# 新式类
c = C() # type(c) => <class '__main__.C'> #新式类可以直接使用type来查看数据类型
d = D()
区别二:多重继承的查找顺序不同
经典类和新式类的继承关系
代码展示:
class A:
pass
#def test(self):
# print("this is A")
class B(A):
pass
#def test(self):
# print("this is B")
class C(A):
pass
#def test(self):
# print("this is C")
class D(B):
pass
#def test(self):
# print("this is D")
class E(C):
pass
#def test(self):
# print("this is E")
class F(D,E):
pass
#def test(self):
# print("this is F")
f = F()
f.test()
经典类
在python2中多重继承的查找顺序:
经典类 => 深度优先算法
F -> D -> B -> A -> E -> C
新式类
新式类 => C3算法
我们可以通过 F.mro(), F.__mro__ 方法直接 查看到查找到父类的顺序
F -> D -> B -> E -> C -> A -> Object
解析列表:
A => [AO] => AO
B(A) => B+[AO] => BAO
C(A) => C+[AO] =>CAO
D(B) => D+[BAO] => DBAO
E(C) => E+[CAO] => ECAO
F(D,E) => F+[DBAO]+[ECAO]
=> FDBECAO
1. 将自身放到解析顺序中
2. 接下来出现的类,如果在后面解析列表中没有出现的话,直接将该类放到解析顺序中
如果出现了,再看后面的类(再解析后面的类)
多态:多态是指同一种操作或方法可以在不同的对象上产生不同的行为。
其实就是一个功能,展现多种形态
鸭子类型:
一只鸟,游起来泳来像一只鸭子,走起路来像一只鸭子,它就是一只鸭子
接收一个鸭子数据(swim,walk) => 等于传递一个鸟数据(swim, walk) --》因此在使用(swim, walk)的时候呈现多种形态
多态示例:
#创建一个功能
def MoneyPay(obj):
obj.pay()
# 可以调用多种状态(类的方法)
class WePay():
def pay(self):
print("this is wepay!")
class AliPay():
def pay(self):
print("This is alipay")
#调用方法(一个功能,多种形态)
wepay1 = WePay()
MoneyPay(wepay1)
alipay1 = AliPay()
MoneyPay(alipay1)
静态方法和类方法:
属性和方法的种类:
# 属性: 类属性和实例属性
# 方法: 实例方法、静态方法、类方法
示例代码:实例方法、静态方法、类方法的定义和使用
class Person(object):
# 类属性
MAX = 10
# 实例方法
# 实例方法:没有任何修饰,第一个参数self
def __init__(self, name): #self代表实例本身
self.name = name
# 静态方法
# 静态方法:使用@staticmethod装饰器,没有额外的参数
# 写在函数/类上方用@修饰对象称为装饰器
# 如果定义一个类中方法的时候,没有用到类和实例相关的数据时,可以定义成静态方法
@staticmethod
def static_method(): #括号中什么都没有
print("this is a static method")
def instance_method(self):
# 给实例添加了一个MAX
# self.MAX = 20
self.__class__.MAX = 20 #在实例方法中修改 类属性 的变量,需要使用self.__class__.类属性
print(f"this is a instance method:{self}")
# 类方法
# 当在方法中需要类(类属性)中数据,可以把它定义成类方法
# 类方法:使用@classmethod修饰,有一个默认的参数 cls=>表示当前类
@classmethod
def class_method(cls): #cls表示当前的类
# cls.MAX = 20
print(f"this is a class method:{cls}")
#实例调用方法
p1 = Person("Cici")
# 调用方法
p1.static_method() #不代表什么,直接运行函数得到的结果
p1.class_method() #代表类
p1.instance_method() #代表实例
# 类调用方法
Person.static_method()
Person.class_method()
# 类名.实例方法() 不可以调用 会报错
# Person.instance_method()
print(Person.MAX)
# 即没有用到类数据,也没有用到实例数据:@staticmethod
# 用到类数据,没有用到实例数据:@classmethod
# 用到实例数据,没有用到类数据:实例方法
# 即用到了实例数据,又用到了类数据:实例方法 self.__class__
结果输出:
this is a static method #静态方法
this is a class method:<class '__main__.Person'> #类方法
this is a instance method:<__main__.Person object at 0x000001E5997DCF10> #实例方法
什么时候使用静态方法呢?
如果定义一个类中方法的时候,没有用到类和实例相关的数据时,可以定义成静态方法。
什么时候使用类方法呢?
当在方法中需要类(类属性)中数据,可以把它定义成类方法
调用静态、类、实例方法的条件:
# 即没有用到类数据,也没有用到实例数据:@staticmethod
# 用到类数据,没有用到实例数据:@classmethod
# 用到实例数据,没有用到类数据:实例方法
# 即用到了实例方法,又用到了类数据:实例方法 + self.__class__.类属性
python中下划线的使用:
python使用下划线的时候:
_user_name = 0 # 单下划线
__user_name = 0 # 双下划线
go中使用下划线的时候:
# file, _ = OpenFile()
# 在go中如果丢弃某个数据放到_变量中
python中的下划线:
单下划线开头的变量/函数/属性/方法/类--》保护对象 => 外部还是可以用
双下划线开头的变量/函数/属性/方法/类--》私有对象 => 只在自己空间中生效
缺点:
使用通配符(*)的方式导入文件/模块的时候,以单下划线_ 和 双下划线__开头的对象是不会被导入进去的
from 模块名 import *
示例:python中内置特殊变量或特殊方法一般都是用双下划线__开头双下划线结尾的
# python内置特殊变量或方法一般都是用双下划线开头双下划线结尾
print(__file__) # 当前文件的绝对路径
print(__name__) # 当前运行的模块名(__main__或模块路径)
print(__doc__) # 当前文件/函数/类 文档注释
print(a.__class__) # a是哪个类,返回当前类
print(B.__bases__) # 查看B的父类有哪些
from requests import get
print(get.__module__) # 查看当前模块名
#例如:
def test():
"""
this is a test function
:return:
"""
pass
print(test.__doc__) # 当前文件/函数/类 文档注释
========
#定义两个类:
class A(object):
pass
class B(A):
pass
a = A()
b = B()
print(a.__class__) # a是哪个类,返回当前类
print(B.__bases__) # 查看B的父类有哪些
print(dir(A))
通过print(dir(A))来查看A类可以使用哪些方法,其中就包含了很多的双下划线的方法
通过代码来实现单下划线 和 双下划线不同的功能
class Parent:
tmp = 'tmp'
_min = 0 # 保护变量
__max = 10 # 私有变量,只能在当前类的内部使用(子类也用不了)
def __make(self): #私有方法
print("这是一个私有方法")
def _make2(self): #保护方法
print("这是一个保护方法")
def show(self):
print(f"_min:{self._min}, __max:{self.__max}")
class Child(Parent):
def show(self):
# print(f"__max:{self.__max}")
print(f"__max:{self._min}")
#定义实例
p = Parent()
c = Child()
#输出当前类可用的属性和方法
print(dir(p))
print(dir(c))
print(Child.__dict__)
print(Parent.__dict__)
#调用show()方法
p.show()
# python所谓的私有,实际上也是可以访问到的,方法特殊一些,如下面的p._Parent__max方式访问
print(p._min, p._Parent__max)
#调用show()方法
c.show()
print(c._Parent__max)
p._make2() #可以访问包含方法
# p.__make() #但是不可以访问私有方法
实验:回合制攻击游戏:
游戏介绍:
回合制游戏:两人进行到一个房间,相互攻击
创建Game类:游戏
交互式菜单:
创建角色,创建房间,
添加角色到房间,
房间满员自动开始游戏
创建Room类:房间
房间名,房间编号,房间成员,房间最大人数
加入房间:房间满员自动开始游戏(player1, player2 )
room.add(player)
创建Role类:角色
初始血量100,初始积分100,
名字、血量、积分、当前所在房间
攻击 a.attack(b)随机掉血(10-30)
role.join(room)文章来源:https://www.toymoban.com/news/detail-605412.html
代码:文章来源地址https://www.toymoban.com/news/detail-605412.html
#回合制游戏:两人进入到一个房间,相互攻击
#创建Game类:游戏
# 交互式菜单:创建角色,创建房间,添加角色到房间,房间满员自动开始游戏
#创建Room类:房间
# 房间名,房间编号,房间成员,房间最大人数
# 加入房间:房间满员自动开始游戏(player1,player2)
# room.add(player)
#创建Role类:角色
# 初始血量100、初始积分100
# 名字、血量、积分、当前所在房间
# 攻击 a.attack(b)随机掉血(10-30)
# role.join(room)
class Game:
flag = 0
def __init__(self):
self.player = {}
name = input("请输入要创建的角色名:")
self.player[name] = Role(name, 100, 30)
self.player[name].show()
room_name = input("请输入要创建的房间名:")
room_number = int(input("请输入要房间人数:"))
self.room = Room(room_name, 0, room_number)
self.room.add(name)
self.room.show()
def start(self):
choice = input("1.继续创建角色\n2.邀请角色加入房间\n请输入:")
if choice == "1":
name = input("请输入要创建的角色名:")
self.player[name] = Role(name, 100, 30)
self.player[name].show()
if choice == "2":
player_name = input("请输入被邀请人名字:")
self.room.add(player_name)
def attack(self):
for i in self.player:
if not self.player[i].flag2:
print(f"{i}发动攻击!")
name = input("请输入要攻击玩家的名字:")
self.player[i].attack_obj(self.player[name])
self.player[name].show()
else:
print(f"游戏结束!")
self.flag = 1
for j in self.player:
self.player[j].show()
class Room:
room_member = []
flag = 0
def __init__(self, room_name, number, max_person):
self.room_name = room_name
self.number = number
self.max_person = max_person
def add(self, player):
self.room_member.append(player)
self.show()
if len(self.room_member) == self.max_person:
print("房间人数已满,游戏开始")
self.flag = 1
def show(self):
print(f"房间名:{self.room_name},房间号:{self.number},房间最大人数是:{self.max_person}")
print("房间成员有:", self.room_member)
import random
class Role:
INIT_HP = 100
score = 100
flag2 = 0
def __init__(self, name, hp = None, attack = 50):
self.name = name
if hp:
self.hp = hp
else:
#self.hp = self.INIT_HP
self.hp = self.__class__.INIT_HP
#攻击上限
self.attack = attack
def show(self):
print(f"{self.name}当前的血量为:{self.hp},当前的积分为:{self.score}")
def attack_obj(self, att_obj):
if self.hp:
x = random.randint(1, self.attack)
print(f"{self.name}对{att_obj.name}造成了{x}点伤害")
if att_obj.hp < x:
print(f"{att_obj.name}玩家死亡")
att_obj.hp = 0
att_obj.flag2 = 1
self.score += 1
else:
att_obj.hp -= x
game = Game()
while not game.room.flag:
game.start()
while not game.flag:
game.attack()
import random
class Role():
blood = 100
grade = 100
defence = 0
def __init__(self,name,room):
self.name = name
self.room = room
print(f"角色{self.name}创建成功,当前房间号为:{self.room}")
def attack(self,name):
if self.blood > 0:
i = random.randint(10,30)
if self.defence >= i:
self.defence -= i
else:
name.blood = name.blood - (i-self.defence)
print(f"{self.name}受到{i}点伤害,当前剩余血量:{name.blood}")
if name.blood <= 0:
print(f"{self.name} died.game over!")
else:
print("玩家已阵亡,请重新开始游戏")
def updefence(self):
if self.blood>0 and self.grade >= 10:
i = random.randint(10,20)
self.grade -= 10
self.defence += i
print(f"{self.name}增加防御{i}点,当前防御为:{self.defence}")
elif self.grade < 10:
print("积分不足")
def bigskill(self,name):
#无视防御
if self.blood>0 and self.grade >= 40:
self.grade -= 40
i = random.randint(30,60)
name.blood -= i
print(f"{self.name}受到大招伤害{i}点,当前剩余血量:{name.blood}")
if name.blood <= 0:
print(f"{self.name} died.game over!")
elif self.grade < 40:
print("积分不足,无法使用")
elif self.blood < 0:
print("玩家已阵亡,请重新开始游戏")
class Room():
roommax = 2
def __init__(self,roomname,roomnum,player1,player2):
self.room_name = roomname
self.room_num = roomnum
self.player1 = player1
self.player2 = player2
print(f"当前房间为{self.room_name}{self.room_num}")
print(f"房间成员:{self.player1},{self.player2}")
if self.player1 and self.player2:
print("游戏开始")
self.start()
else:
print("角色数量不足,无法开始游戏")
def start(self):
role1 = Role(self.player1, self.room_num)
role2 = Role(self.player2, self.room_num)
menu_data = """
1.攻击
2.提高防御
3.发动大招
"""
while True:
print(menu_data)
choice = input("输入角色1的技能序号:")
if choice == "1":
role1.attack(role2)
if role2.blood <= 0:
break
elif choice == "2":
role1.updefence()
elif choice == "3":
role1.bigskill(role2)
if role2.blood <= 0:
break
choice = input("输入角色2的技能序号:")
if choice == "1":
role2.attack(role1)
if role1.blood <= 0:
break
elif choice == "2":
role2.updefence()
elif choice == "3":
role2.bigskill(role1)
if role1.blood <= 0:
break
class Game():
def start(self):
menu_data = """
1.创建角色
2.创建房间
"""
while True:
print(menu_data)
choice = input("请输入你的操作:")
if choice == "1":
n = 1
while n<3:
print("提示:你需要创建两名角色才能开始游戏!")
name = input("请输入角色名称:")
room = input("请输入房间号:")
if n==1:
player1 = name
Role(player1, room)
n += 1
print(f"当前角色数量为{n-1}")
else:
player2 = name
Role(player2, room)
n += 1
print(f"当前角色数量为{n-1}")
elif choice == "2":
roomname = input("请输入需要创建的房间名称:")
roomnum = input("请输入需要创建的房间号")
room1 = Room(roomname, roomnum, player1, player2)
else:
print("错误输入!请重新输入:")
if __name__ == "__main__":
game = Game()
game.start()
到了这里,关于python 面向对象编程的特点 - 封装 - 继承(经典类、新式类) - 多态 - 静态方法、类方法 - 下划线的使用 - 回合制攻击游戏实验的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!