类与实例
# 面向过程编程 ,根据程序执行顺序,从上到下编写函数,更适合机器运行
user1 = {'name':'tom','hp':100}
user2 = {'name': 'jerry','hp': 80}
def print_role(rolename):
print('name is %s, hp is %s' %(rolename['name'], rolename['hp']) )
print_role(user1)
print_role(user2)
'''
name is tom, hp is 100
name is jerry, hp is 80
'''
# 面向对象编程,更符合我们人类的思维习惯,把相同的东西进行归纳和总结
class Player(): # 定义一个类,类名字开头大写
# __init__当引用到这个类的时候,在进行实例化之后,会自动执行这个方法
def __init__(self,name,hp):
self.name = name # self表示这个类进行了实例化之后,实例的本身
self.hp = hp
def print_role(self): # 定义一个类的方法
print('name is %s, hp is %s' %(self.name, self.hp))
user1 = Player('tom',100) # 类的实例化
user2 = Player('jerry',90)
user1.print_role()
user2.print_role()
'''
name is tom, hp is 100
name is jerry, hp is 90
'''
增加类的属性和方法
class Player: # 定义一个类
def __init__(self, name, hp, occu):
self.name = name # 面向对象中变量被称作属性
self.hp = hp
self.occu = occu # 把传递的变量和实例做一个绑定
def print_role(self): # 面向对象中函数被称作方法
print("%s: %s %s" % (self.name, self.hp, self.occu))
# 在类中实现的方法,第一个参数一定是self
def updateName(self, newname): #用updateName接受一个参数,newname
self.name = newname #将newname赋给当前实例的名字
# 游戏里除了玩家之外,还希望有怪物类
class Monster:
"定义怪物类"
"""
在实际开发过程中,有一些类我们目前不想编写功能,不想实现
定义好这个类,我们希望他什么都不写,程序也不要报错,使用pass关键字
"""
pass
# 我们把warrior、master作为参数传递到Player类中,进而对user1、user2增加属性
user1 = Player("tom", 100, "warrior") # 职业战士
user2 = Player("jerry", 90, "master") # 职业法师
user1.print_role()
user2.print_role()
'''
tom: 100 warrior
jerry: 90 master
'''
# 更改user1的姓名
user1.updateName('wilson')
user1.print_role()
'''
wilson: 100 warrior
'''
# 这种情况下,我们其实不需要这个updateName也可以修改类里面的变量
user1.name = ('aaa')
user1.print_role()
'''
aaa: 100 warrior
'''
# 如果类的属性不想让别人访问到的话,可以在类的属性前面加两个下划线__name,这样变量就不会被实例访问到
class Player:
def __init__(self, name, hp, occu):
self.__name = name
self.hp = hp
self.occu = occu
def print_role(self):
print("%s: %s %s" % (self.__name, self.hp, self.occu))
def updateName(self, newname):
self.name = newname
user1 = Player("tom", 100, "warrior")
user1.print_role()
# tom: 100 warrior
# 更改user1的姓名
user1.updateName("wilson")
user1.print_role()
# tom: 100 warrior
user1.name = "aaa"
user1.print_role()
# tom: 100 warrior
user1.__name = "aaa"
user1.print_role()
# tom: 100 warrior
# 这时我们要修改类当中的某个属性时,一定要通过方法去改变,不能随意的通过赋值的方法来改变,这个特性称为类的封装
继承、多态
猫科动物与猫
class Monster:
"定义怪物类"
def __init__(self, hp=100):
self.hp = hp
def run(self):
print("移动到某个位置")
a1 = Monster(200)
print(a1.hp)
print(a1.run())
'''
100
移动到某个位置
None
'''
class Animals(Monster):
"普通怪物"
def __init__(self, hp=10):
self.hp = hp
a2 = Animals(1)
print(a2.hp)
print(a2.run())
'''
1
移动到某个位置
None
'''
class Monster:
"定义怪物类"
def __init__(self, hp=100):
self.hp = hp
def run(self):
print("移动到某个位置")
class Animals(Monster):
"普通怪物"
def __init__(self, hp=10):
# 子类当中的hp属性和父类中的hp属性是重复定义的,当子类被大量引用的时候,这段会非常消耗计算机资源
self.hp = hp
class Animals(Monster):
# 可以用super方法:在父类中初始化了某些属性,子类不用重复的再去初始化
def __init__(self,hp=10):
super().__init__(hp)
class Monster:
"定义怪物类"
def __init__(self, hp=100):
self.hp = hp
def run(self):
print("移动到某个位置")
def whoami(self):
print("我是怪物父类")
class Boss(Monster):
"Boss类怪物"
def __init__(self, hp=1000):
super().__init__(hp)
def whoami(self):
print("我是怪物我怕谁")
# 父类和子类定义同名方法时,子类的调用会覆盖父类的方法
# 实例化Boss类时,whoami方法会随着实例将父类的whoami方法覆盖掉
a3 = Boss(800)
a3.whoami()
# 我是怪物我怕谁
'''
这种方法只有在实际使用的时候,才会知道调用的是子类还是父类,说明这种方法在运行的时候会有多种状态
这是面向对象编程的一种特性:多态 继承和多态都是面向对象编程的重要特性
'''
# 判断子类 tpye isinstance
class Monster:
"定义怪物类"
def __init__(self, hp=100):
self.hp = hp
def run(self):
print("移动到某个位置")
class Animals(Monster):
# 可以用super方法:在父类中初始化了某些属性,子类不用重复的再去初始化
def __init__(self, hp=10):
super().__init__(hp)
class Boss(Monster):
"Boss类怪物"
def __init__(self, hp=1000):
super().__init__(hp)
def whoami(self):
print("我是怪物我怕谁")
a1 = Monster(100)
a2 = Animals(10)
a3 = Boss(800)
# tpye可以获得对象是属于哪个类的
print("a1的类型%s" % type(a1))
print("a2的类型%s" % type(a2))
print("a3的类型%s" % type(a3))
'''
a1的类型<class '__main__.Monster'>
a2的类型<class '__main__.Animals'>
a3的类型<class '__main__.Boss'>
'''
#要判断a2是否为Monster的子类,可以用isinstance,判断类之间的继承关系
print(isinstance(a2, Monster))
# True
# Python3中元组、字符串、列表、整数,都是Class类,这就是面向对象编程,这些类的父类都继承于object
自定义with
with open () as f:
# 使用with,如果文件打开失败,我们不用处理异常,with语句会自动帮我们处理异常,with语句将异常与面向对象结合了起来
class Testwith:
def __enter__(self): # 类初始化时会被调用
print("run")
def __exit__(self, exc_type, exc_val, exc_tb): # 类结束时会被调用
print("exit")
with Testwith():
print("Test is runing")
'''
run
Test is runing
exit
'''
# 抛出异常与类的功能结合,我们就不用再写try catch except的方式来捕获异常,可以直接使用with的方式简化异常的编写
class Testwith:
def __enter__(self): # 类初始化时会被调用
print("run")
def __exit__(self, exc_type, exc_val, exc_tb): # 类结束时会被调用
# 如果没有异常,会抛出None值
if exc_tb is None:
print("正常结束")
else:
print("has error %s" % exc_tb)
with Testwith():
print("Test is runing")
# 手动抛出异常
raise NameError("testNameError")
'''
run
Test is runing
has error <traceback object at 0x0000020C5C5A0680>
Traceback (most recent call last):
File "c:\Users\Leon zhao\Desktop\demo.py", line 17, in <module>
raise NameError("testNameError")
NameError: testNameError
'''