一篇文章带你再回顾Python面向对象

87 阅读5分钟

类与实例

# 面向过程编程 ,根据程序执行顺序,从上到下编写函数,更适合机器运行
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

c225909b14be01166afa9264426d9e68.png

自定义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
'''