<四>面向对象的学习、反射、异常处理
<1>面向对象编程(Object-Oriented Programming )介绍
面向对象学习三字经:找名词、加属性、连关系
面向对象的特性:封装、继承、多态
OOP编程是利用“类”和“对象”来创建各种模型来实现对真实世界的描述,使用面向对象编程的原因一方面是因为它可以使程序的维护和扩展变得更简单,并且可以大大提高程序开发效率 ,另外,基于面向对象的程序可以使它人更加容易理解你的代码逻辑,从而使团队开发变得更从容。
①Class 类
一个类即是对一类拥有相同属性的对象的抽象、蓝图、原型。在类中定义了这些对象的都具备的属性(variables(data))、共同的方法
②Object 对象
一个对象即是一个类的实例化后实例,一个类必须经过实例化后方可在程序中调用,一个类可以实例化多个对象,每个对象亦可以有不同的属性,就像人类是指所有人,每个人是指具体的对象,人与人之前有共性,亦有不同
③Encapsulation 封装
在类中对数据的赋值、内部调用对外部用户是透明的,这使类变成了一个胶囊或容器,里面包含着类的数据和方法
④Inheritance 继承
一个类可以派生出子类,在这个父类里定义的属性、方法自动被子类继承
⑤Polymorphism 多态
多态是面向对象的重要特性,简单点说:“一个接口,多种实现”,指一个基类中派生出了不同的子类,且每个子类在继承了同样的方法名的同时又对父类的方法做了不同的实现,这就是同一种事物表现出的多种形态。
封装
实例化例子:
object 新试类的写法 、__init__()叫做初始化方法(或构造方法)可以添加类的属性
self=实例对象r1
r1=Role("shikai","police","AK47") # 把一个类变成一个具体对象的过程叫实例化(初始化一个类,创建一个对象),把属性传给__init__()方法
#_*_coding:utf-8_*_ #__author__:"shikai" class Role(object): n=123 #类变量 l=[] def __init__(self,name,role,weapon,life_value=100,money=15000,age=10): #构造方法 传参数 self.name=name # 实列变量 (静态属性)作用域就是实列本身 self.role=role #r1.role=role r1相当于self self.weapon=weapon self.life_value=life_value self.__age=age ##私有属性 外部不可调用 在内部函数可以调用 self.money=money r1=Role("shikai","police","AK47") # 把一个类变成一个具体对象的过程叫实例化(初始化一个类,创建一个对象) Role.buy_gun(r1,'98k')
整个过程
继承:继承父类的方法和属性,继承创建的新类称为“子类”或“派生类”,被继承的类称为“基类”、“父类”或“超类”
①子类继承父类时,要先将父类属性添上 :name、age为父类属性、ideal为子类属性
def __init__(self,name,age,ideal): #在子类要添加新属性时要先添加父类的属性
② People.__init__(self,name,age) #(老式类)调用父类属性
super(Man,self).__init__(name,age) #(新式类) #另一个调用父类属性方法(解决多继承要写多个调用方法的困扰)
③子类实例化时要把父类属性加上
m1=Man("shikai",10,"python") #继承时候要把父类属性添上
#_*_coding:utf-8_*_ #__author__:"shikai" #class People(): #经典类 class People(object): #(新式类写法) ----------( 父类 ) def __init__(self,name,age): self.name=name self.age=age self.friends=[] def eat(self): print("{} eat good food!".format(self.name)) def talk(self): print("{} is talkking".format(self.name)) def sleep(self): print("{} is sleep".format(self.name)) class Relation(object): def make_friends(self,obj): print("{} is making friiends with {}!".format(self.name,obj.name)) self.friends.append(obj) class Man(People,Relation): #类的继承(子类) def __init__(self,name,age,ideal): #在子类要添加新属性时要先添加父类的属性 #People.__init__(self,name,age) #调用父类属性 super(Man,self).__init__(name,age) #(新式类) #另一个调用父类属性方法(解决多继承要写多个调用方法的困扰) self.ideal=ideal def eat(self): People.eat(self) #在父类方法上添加新方法 print("it is perfect!") def play(self): print("{} play lol,but never give up his {} ".format(self.name,self.ideal)) class Woman(People,Relation): def birth(self): print("{} will birth a little baby".format(self.name)) m1=Man("shikai",10,"python") #继承时候要把父类属性添上 # m1.eat() # # m1.play() w1=Woman("zhonghui",10) m1.make_friends(w1) #两个对象联系 print(m1.name) print(m1.friends[0].name)
继承、多态
一个接口,多重调用。在继承父类之后可以添加新的方法和属性。
如:在子类中添加了ideal属性和eat、play方法
class Man(People,Relation): #类的继承(子类) def __init__(self,name,age,ideal): #在子类要添加新属性时要先添加父类的属性 #People.__init__(self,name,age) #调用父类属性 super(Man,self).__init__(name,age) #(新式类) #另一个调用父类属性方法(解决多继承要写多个调用方法的困扰) self.ideal=ideal def eat(self): People.eat(self) #在父类方法上添加新方法 print("it is perfect!") def play(self): print("{} play lol,but never give up his {} ".format(self.name,self.ideal))
子类联系:实例对象:m1=Man("shikai",10,"python")和实例对象: w1=Woman("zhonghui",10)通过继承父类Relation里的方法即可实现联系
#父类 class People(object): #(新式类写法) ----------( 父类 ) def __init__(self,name,age): self.name=name self.age=age self.friends=[] class Relation(object): def make_friends(self,obj): print("{} is making friiends with {}!".format(self.name,obj.name)) self.friends.append(obj) #子类1 class Man(People,Relation): #类的继承(子类) def __init__(self,name,age,ideal): #在子类要添加新属性时要先添加父类的属性 #People.__init__(self,name,age) #调用父类属性 super(Man,self).__init__(name,age) #(新式类) #另一个调用父类属性方法(解决多继承要写多个调用方法的困扰) self.ideal=ideal #子类2 class Woman(People,Relation): def birth(self): print("{} will birth a little baby".format(self.name)) #实例化 m1=Man("shikai",10,"python") w1=Woman("zhonghui",10) #联系 m1.make_friends(w1) #结果:shikai is making friiends with zhonghui!
静态方法:@staticmethod装饰器即可把其装饰的方法变为一个静态方法,静态方法是不可以访问实例变量或类变量的,一个不能访问实例变量和类变量的方法,其实相当于跟类本身已经没什么关系了,它与类唯一的关联就是需要通过类名来调用这个方法,静态方法:实际上与类没什么关系,tell()只是一个函数不再是类
#静态方法 class Dog(object): def __init__(self,name): self.name=name @staticmethod #静态方法:实际上与类没什么关系,tell()只是一个函数不再是类 def tell(): print("你好") def eat(self): print('{} is eating'.format(self.name)) d=Dog("二哈") d.tell() d.eat()
类方法:@classmethod装饰器实现,类方法和普通方法的区别是, 类方法只能访问类变量,不能访问实例变量
#类方法 class Dog(object): name='类变量' #类变量 def __init__(self, name): self.name = name #实例变量 @classmethod def eat(self): print("%s is eating" % self.name) d = Dog("二哈") d.eat()
属性方法:@property把一个方法变成一个静态属性,
注:eat此时是静态方法也就是变成了一个函数,同个类名调用 d.eat
#属性方法 class Dog(object): def __init__(self, name): self.name = name @property def eat(self): print(" %s is eating" % self.name) d = Dog("二哈") d.eat
<2>反射
实例:判断一个字符串在一个类里有相同的方法名,比如用户输入:eat,如果类中有eat方法就执行。
hasattr :检查成员
getattr :获取成员 、执行方法
setattr :设置成员 (把类外的函数动态的添加到类中)
delattr :删除成员
#!_*_coding:utf-8_*_ #__author__:"shikai" """ hasattr(obj,str) :判断对象boj里是否有对应的str方法 getattr(obj,str) :获取obj对象的str方法的内存地址 setattr(obj,str,z):相当于obj.str=z 把方法添加到class里面 delattr(obj,str) :删除obj里的str方法 """ def talk(self): print("{} is talking".format(self.name)) class Dog(object): def __init__(self,name): self.name=name def eat(self): print("{} is eatting".format(self.name)) d=Dog('二哈') choice=input(">>:") if hasattr(d,choice): func=getattr(d,choice) func() #执行方法 #delattr(d,choice) #删除方法 else: setattr(d,choice,talk) #动态添加方法 func=getattr(d,choice) #获得方法内存地址 func(d) #执行添加后的方法
<3>异常处理
常用异常:
AttributeError 试图访问一个对象没有的树形,比如foo.x,但是foo没有属性x IOError 输入/输出异常;基本上是无法打开文件 ImportError 无法引入模块或包;基本上是路径问题或名称错误 IndentationError 语法错误(的子类) ;代码没有正确对齐 IndexError 下标索引超出序列边界,比如当x只有三个元素,却试图访问x[5] KeyError 试图访问字典里不存在的键 KeyboardInterrupt Ctrl+C被按下 NameError 使用一个还未被赋予对象的变量 SyntaxError Python代码非法,代码不能编译(个人认为这是语法错误,写错了) TypeError 传入对象类型与要求的不符合 UnboundLocalError 试图访问一个还未被设置的局部变量,基本上是由于另有一个同名的全局变量, 导致你以为正在访问它 ValueError 传入一个调用者不期望的值,即使值的类型是正确的
抓住异常:
#_*_coding:utf-8_*_ #__author__:"shikai" try: name[2] data[name] open("text.txt") except (IndexError,TypeError) as e: #同时抓取多个特定异常错误 print(e) except Exception as e: #抓取全部异常 print("异常",e) else: #正常情况 print("一切正常") finally: #不管错没错都会打印 print("不管错没错都会打印")
自定义异常:
#_*_coding:utf-8_*_ #__author__:"shikai" class shikaiError(Exception): def __init__(self,masg): self.masg=masg try: raise shikaiError("数据库连不上") #触发这个异常 except shikaiError as e: print(e)