Python面向对象
1.面向对象的定义
面向对象,即将函数(方法)进行分类和封装。
创建对象:
1 #class 是创建类的关键字,People 是类名 2 class People: 3 #定义一个方法即函数 4 def get_name(self,name): 5 print(name) 6 7 nanren = People() # 创建一个对象nanren 8 nanren.get_name('男人') # 男人 9 nvren = People() # 创建一个对象nvren 10 nanren.get_name('女人') # 女人
2.面向对象的三个特性
1)封装
将公用的字段放在__init__(self)中,类中的其他方法可以调用,也称构造方法。
1 class People: 2 #构造方法,将接受到的fname和lname进行保存 3 # self 就是创建的对象名称 4 def __init__(self,fname,lname): 5 self.fname = fname 6 self.lname = lname 7 8 # get_fullname(self)称为自定义方法 9 def get_fullname(self): 10 full_name = self.fname + self.lname 11 print(full_name) 12 13 obj = People('slito','bo') # 创建对象时类传递的参数就是__init__中定义的形参 14 obj.get_fullname() # slitobo
2)继承
任何派生类(子类)都继承基类(父类)的内容。
#定义一个父类father class father: def f1(self): print('f1.test') def f2(self): print('f2.test') #定义一个类son,继承father class son(father): def s1(self): print('hello son') # 定义一个子类的对象obj_son1,该对象可以访问父类father中的方法。 obj_son1 = son() obj_son1.f1() # f1.test obj_son1.f2() # f2.test
在子类的方法中执行父类的方法。
class son(father): def s1(self): print('hello son') def s2(self): super(son,self).f2() # 第一种方法 # father.f2(self) # 第二种方法 obj_son1 = son() obj_son1.s2() # f2.test
多继承
一个类可以继承多个父类。当不同的类中有相同的方法时,根据相应的查找顺序查找。
查找顺序分为: 深度查找和广度查找。
深度查找:执行obj.bar()后,先找D,D中没有找B,B中没有,找到A,A中没有,再找C。找到任何一个先停止。

class A: def bar(self): print('A') class B(A): pass class C: def bar(self): print('C') class D(B, C): pass obj = D() obj.bar() # A
广度查找:执行obj.bar()后,先找D,D中没有找B,B中没有,再找C,C中没有,再找A。找到任何一个先停止。

class A: def bar(self): print('A') class B(A): pass class C(A): def bar(self): print('C') class D(B, C): pass obj = D() obj.bar() # C
总结:1)左侧优先查找,一路查到底,找到则停止。
2)相同根,广度查找,最后找根。
3)多态
同一种事物(类)有多种状态,如动物又分为,人,猪,狗等。
多态以继承为基础。
class Animals: def run(): print("子类可以使用我") class people(Animals): def run(): print("我可以直立行走和使用语言") class pig(Animals): def run(): print("我能睡")
多态性
一种执行方式,不同执行效果。
def func(obj): obj.run() func(peo1) #执行效果一 func(pig1) #执行效果二 func(d1) #执行效果三
3.面向对象的类成员

1)字段
普通字段 & 静态字段
静态字段存放在类中,节省内存。对象使用字段会浪费内存。
如果不使用静态字段country,则需要在每个对象调用getname方法时,传入“中国”,则“中国”会占用对象的内存。
class provice: country = '中国' # 静态字段 # name是普通字段 def getname(self,name): print(self.country,name) obj = provice() obj.getname('陕西') # 中国 陕西 obj.getname('浙江') # 中国 浙江
2)方法
普通方法 & 静态方法 & 类方法
class provice: country = '中国' # 静态字段 # 普通方法 def getname(self,name): print(self.country,name)
# 静态方法,不需要self,和普通函数一样 @staticmethod def getstatic(): print('static')
# 类方法,cls = 类名 @classmethod def getclass(cls): print(cls) print(cls.country) obj = provice() obj.getstatic() # static obj.getclass() # <class '__main__.provice'> # 中国
3)属性
@property 此装饰器将方法调用变成字段调用的方式
class foo: @property def get_name(self): print('属性测试') obj = foo() # obj.get_name() # TypeError: 'NoneType' object is not callable obj.get_name # 属性测试
方法.setter/deleter(仅作一一对应)
class foo: @property def get_name(self): print('属性测试') @get_name.setter def get_name(self,val): print(val) @get_name.deleter def get_name(self): print('deleter') obj = foo() obj.get_name # 属性测试 obj.get_name = 123 # 123 del obj.get_name # deleter
4.面向对象的特殊方法
1)__doc__ 类的描述信息
class Foo: ''' 类的描述''' def func(self): pass print (Foo.__doc__) # 类的描述
2)__module__ 对象属于那个模块
from lei import foo obj = foo() print(obj.__module__) # lei
3)__class__ 操作对象的类是哪一个
from lei import foo obj = foo() print(obj.__class__) # lei.foo
4)__call__ 对象加括号执行__call__中定义的内容
class foo: def __call__(self, *args, **kwargs): print('call test') obj = foo() obj() # call test
5)__dict__ 将构造方法中定义的变量与创建对象的时给的值,生成字典。
class foo: def __init__(self,name,age): self.name1 = name self.age1= age obj = foo('slitobo','27') print(obj.__dict__) # {'name1': 'slitobo', 'age1': '27'}
6)__str__ 将__str__方法中的返回值(字符串)返回给对象
1 class car: 2 def __init__(self,color,sign): 3 self.color = color 4 self.sign = sign 5 def __str__(self): 6 msg = "这是一辆"+self.color+"的"+self.sign 7 return msg 8 9 dazhong = car("白色","大众") 10 print(dazhong) # 这是一辆白色的大众
7)__getitem__/__setitem__/__delitem__ 处理KEY-VALUE类型的数据,对对象进行获取/设置/删除key的操作时,引用这三个方法。
1 class Foo(): 2 3 def __getitem__(self, key): 4 print('__getitem__', key) 5 6 def __setitem__(self, key, value): 7 print('__setitem__', key, value) 8 9 def __delitem__(self, key): 10 print('__delitem__', key) 11 12 obj = Foo() 13 14 result = obj['k1'] # __getitem__ k1 15 obj['k2'] = 'test' # __setitem__ k2 test 16 del obj['k1'] # __delitem__ k1
8)__iter__ ,该方法的返回值为可迭代对象,对象 = 返回值 ,与iter()函数一样的效果
1 class foo: 2 def __init__(self,list1): 3 self.list1 = list1 4 def __iter__(self): 5 return iter(self.list1) 6 list1=[1,2,3,4] 7 obj = foo(list1) 8 for i in obj: 9 print(i,end=" ") # 1 2 3 4 10 # 函数iter()的效果 11 # list1=[1,2,3,4] 12 # it = iter(list1) 13 # for i in it: 14 # print(i,end=" ") # 1 2 3 4
9)__add__,将两个对象的进行处理,如数字相加/减,字符串组合
1 class foo: 2 def __init__(self,name,age): 3 self.name = name 4 self.age = age 5 def __add__(self, other): 6 return self.age + other.age 7 obj = foo('slito',10) 8 obj2 = foo('slito1',20) 9 obj3 = obj + obj2 10 print(obj3) # 30
* 10)metaclass 和__new__ (还有点疑问)
在之前,创建一个对象,使用"对象=类名()"这种方法创建。进行详解说明创建一个对象的过程。
metaclass :用在类中的方法,表示该类是由谁来创建,默认是由type创建。
#class foo(metaclass=type): #默认 class foo(): pass print(type(foo)) # <class 'type'>
__new__:是在类准备将自身实例化时调用,创建对象。
定义一个类,继承type类,模拟创建实例的过程。
1 class mytype(type): 2 def __init__(self,what,bases=None,dict=None): 3 super(mytype,self).__init__(what,bases,dict) 4 5 def __call__(self, *args, **kwargs): 6 obj = self.__new__(self, *args, **kwargs) 7 self.__init__(obj) 8 9 #object是所有新式类的基类 10 class foo(object): 11 __metaclass__ = mytype 12 def __init__(self): 13 pass 14 def __new__(cls, *args, **kwargs): 15 return object.__new__(cls, *args, **kwargs) 16 17 #obj1 是foo的实例化 18 obj1 = foo() 19 print(obj1) # __main__.foo object at 0x000001CEDE1D2748>
过程说明:
第一步,foo()执行时,由于metaclass是mytype,则由mytype类创建foo类,此时"类名()"调用了__call__()方法,其中self是foo。
第二步,指定foo中的__new__()方法,将类实例化,返回一个值,该值就是foo实例化后的对象。
第三步,由一个变量obj接受上面的返回值,执行self.__init__(obj),self是foo,执行foo中的__init__方法,将obj赋给参数self。
5.异常处理
对可能发生报错的语句块进行捕获处理
如int(num)时,num是数值型则不会报错,如果是num是字符串,则发生Value error
num = input('请输入一个数字:') try: num = int(num) except Exception as e: print('输入有误,请输入数字') else : print(num) finally: print('The end')
try 中的语句块可能会报错。如果报错,则执行except 中的语句块。没有报错,则执行else中的语句。最后都要执行finally语句块。
其中,Exception是捕获所有的错误, 将捕获的错误信息放到e中(e可随便取名称)
自定义异常捕获和主动触发异常
raise 可以主动生成异常。
# 定义一个slitoboerror类,继承Exception class slitoerror(Exception): def __init__(self,msg): self.message = msg #类实例化后返回值为字符串 def __str__(self): return self.message try: # 主动触发异常 raise slitoerror('iamwrong') except slitoerror as e: print(type(e)) # <class '__main__.slitoerror'> print(e) # iamwrong
6.单例模式
节省内存,创建的多个对象使用同一块内存。
使用场景如数据库连接。应用程序与数据库要建立一个连接池,连接池就是一个类,每个连接都是一个对象或者实例。
class foo: __instance = None def __init__(self): self.dbhost = '1.1.1.1' self.port = 3306 self.username = 'mysql' self.pw = 'mysql' @classmethod def get_single_instance(cls): if cls.__instance: return cls.__instance else: cls.__instance = foo() return cls.__instance def chaxun(self): #登录mysql pass mysql_intsance1 = foo.get_single_instance() mysql_intsance2 = foo.get_single_instance() print(mysql_intsance1) # <__main__.foo object at 0x0000019AFEF127F0> print(mysql_intsance2) # <__main__.foo object at 0x0000019AFEF127F0> mysql_intsance1.chaxun() mysql_intsance2.chaxun()

7.反射
反射是通过字符串形式获取对象中字段或者方法。
hasattr()/getattr()/setattr()/delattr()
class foo: country = 'china' def getname(self,name): print(name) obj = foo()
hasattr(o,name) 判断对象中是否存在该名称,存在返回值为True,不在返回值为False
result = hasattr(obj,'country') print(result) # True result = hasattr(obj,'abc') print(result) # False
getattr(o,name[,default]) 获取对象中的名称的值,存在就返回当前值,不存在如果有默认值就返回默认值,没有默认值报错。如果获取的是方法,则获取的是方法的内存地址。
#获取字段 c = getattr(obj,'country',None) print(c) # china #获取方法 fun = getattr(obj,'getname') print(fun) # <bound method foo.getname of <__main__.foo object at 0x0000021D125826D8>> fun('slitobo') # slitobo
setattr(o,name,value) 设置对象中,name = value,name存在则修改。
setattr(obj,'province','zhejiang') c = getattr(obj,'province',None) print(c) # zhejiang
delattr(o,name) 删除对象中name
delattr(obj,'province') c = getattr(obj,'province',None) print(c) # None

浙公网安备 33010602011771号