python开发学习 day26 面向对象(多态、封装、反射。。。。。。)
一、多态
什么是多态:由不同的类实例化所得到的对象,调用同一个方法,执行的逻辑不同
多态的概念指出了对象如何通过他们共同的属性和动作来操作及访问,而不需要考虑其他具体的类
多态表明了动态(又名,运行时)绑定的存在,允许重载及运行时类型确定和验证
--举例
水是一个类,
不同温度,水被实例化成了不同的状态:冰、水蒸气、雾(然而很多人理解到这一步就任务此乃多态,错,fuck,多态是运行时绑定的状态)
(多态体现在由同一个类实例化出的多个对象,这些对象执行相同的方法时,执行的过程和结果是一样的)
(冰,水蒸气,雾,又一个共同的方法就是变成云,但是冰变云,与水蒸气变云,是截然不同的两个过程,虽然调用的方法一样)
例子:
str1 = '123'
l = [1,2,3]
len(str1) -----> str1.__len__()
len(l) ------> l.__len__()
如标黄所示,通过共同属性操作及访问,无需考虑他们的类
#_*_coding:utf-8_*_ __author__ = 'Linhaifeng' class H2O: def __init__(self,name,temperature): self.name=name self.temperature=temperature def turn_ice(self): if self.temperature < 0: print('[%s]温度太低结冰了' %self.name) elif self.temperature > 0 and self.temperature < 100: print('[%s]液化成水' %self.name) elif self.temperature > 100: print('[%s]温度太高变成了水蒸气' %self.name) def aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(self): pass class Water(H2O): pass class Ice(H2O): pass class Steam(H2O): pass w1=Water('水',25) i1=Ice('冰',-20) s1=Steam('蒸汽',3000) # w1.turn_ice() # i1.turn_ice() # s1.turn_ice() def func(obj): obj.turn_ice() func(w1) #---->w1.turn_ice() func(i1) #---->i1.turn_ice() # def func(obj): # obj.turn_ice() # # func(w1) # func(i1) # func(s1)
---多态实际上是依附于继承的两种含义的:“改变”和“扩展”本身就意味着必须有机制去自动选用你改变\扩展过的版本,故无多态,则两种含义就不可能实现
所以,多态实质上是继承的实现细节,那么,让多态与封装、继承两个概念并列,显然是不符合逻辑的
二、封装

约定二:双下划线开头的名字
#_*_coding:utf-8_*_ __author__ = 'Linhaifeng' class People: __star='earth111111111111' __star1='earth111111111111' __star2='earth111111111111' __star3='earth111111111111' def __init__(self,id,name,age,salary): print('----->',self.__star) self.id=id self.name=name self.age=age self.salary=salary def get_id(self): print('我是私有方法啊,我找到的id是[%s]' %self.id) #访问函数 def get_star(self): print(self.__star) p1=People('123123123123','alex','18',100000000) # print(p1.__star) print(People.__dict__) # print(p1.__star) print(p1._People__star) # # p1.get_star() p1.get_star()
小结::类的继承有两层意义,1.扩展 2.改变
多态就是类的这两层意义的一个具体的实现机制,即调用不同的类实例化得对象下的相同的方法,实现的过程不一样
python中的标准类型就是多态概念的一个很好的示范
封装::第一层面的封装,类就是一个麻袋,这本身就是一种封装
第二层面的封装,类中定义私有的,只在类内部使用,外部无法访问(两种约定,一种单下划线开头的名字,一种双下划线开头)
第三层面的封装,明确区分内外,内部的实现逻辑,外部无法知晓,并且为封装到内部的逻辑提供一个访问接口给外部使用(这才是真正的封装,具体实现会在面向对象进阶中讲到)
#_*_coding:utf-8_*_ __author__ = 'Linhaifeng' class Room: def __init__(self,name,owner,width,length,high): self.name=name self.owner=owner self.__width=width self.__length=length self.__high=high def tell_area(self): #此时我们想求的是面积 return self.__width * self.__length *self.__high def tell_width(self): return self.__width r1=Room('卫生间','alex',100,100,10000) # arear=r1.__width * r1.__length print(r1.tell_area())
面向对象概念总结

---python中关于opp的常用术语
1.抽象/实现
2.封装/接口
3.合成(组合)
4.派生/继承/继承结构
5.泛化/特化
6.多态
7.自省/反射
三、反射

class BlackMedium: feture='Ugly' def __init__(self,name,addr): self.name=name self.addr=addr def sell_hourse(self): print('【%s】 正在卖房子,傻逼才买呢' %self.name) def rent_hourse(self): print('【%s】 正在租房子,傻逼才租呢' % self.name) print(hasattr(BlackMedium,'feture')) getattr() # # b1=BlackMedium('万成置地','天露园') # b1.name--->b1.__dic__['name'] # print(b1.__dict__) # # # b1.name # # b1.sell_hourse # print(hasattr(b1,'name')) # print(hasattr(b1,'sell_hourse')) # print(hasattr(b1,'selasdfasdfsadfasdfasdfasdfasdl_hourse')) # # # # print(getattr(b1,'name')) # print(getattr(b1,'rent_hourse')) # func=getattr(b1,'rent_hourse') # func() # # print(getattr(b1,'rent_hourseasdfsa')) #没有则报错 # print(getattr(b1,'rent_hourseasdfsa','没有这个属性')) #没有则报错 # # # # b1.sb=True # setattr(b1,'sb',True) # setattr(b1,'sb1',123) # setattr(b1,'name','SB') # setattr(b1,'func',lambda x:x+1) # setattr(b1,'func1',lambda self:self.name+'sb') # print(b1.__dict__) # print(b1.func) # print(b1.func(10)) # print(b1.func1(b1)) # del b1.sb # del b1.sb1 # delattr(b1,'sb') # print(b1.__dict__)


---动态导入模块...实际上是基于反射
__import__('dic')
module_t=__import__('m1.t') ##无论多少层只记录顶层模块名 print(module_t) # module_t.t.test1() #因此执行时要添加多层目录 # from m1.t import * # from m1.t import test1,_test2 # # test1() # _test2() import importlib m=importlib.import_module('m1.t') print(m) m.test1() m._test2()
四、类的内置attr属性
__setattr__ , __delattr __ , __getattr__
# class Foo: # x=1 # def __init__(self,y): # self.y=y # # def __getattr__(self, item): # print('执行__getattr__') # # f1=Foo(10) # print(f1.y) # print(getattr(f1,'y')) #len(str)--->str.__len__() # f1.sssssssssssssssssssssssssssssssssssss # class Foo: # x=1 # def __init__(self,y): # self.y=y # # def __delattr__(self, item): # print('删除操作__delattr__') # # f1=Foo(10) # del f1.y # del f1.x # # class Foo: # x=1 # def __init__(self,y): # self.y=y # # def __setattr__(self, key, value): # print('__setattr__执行') # # self.key=value # self.__dict__[key]=value # f1=Foo(10) # print(f1.__dict__) # f1.z=2 # print(f1.__dict__) # class Foo: # def __getattr__(self, item): # print('------------->') # # # print(Foo.__dict__) # print(dir(Foo)) # f1=Foo() # # print(f1.x) #只有在属性不存在时,会自动触发__getattr__ # # del f1.x #删除属性时会触发_delattr__ # # f1.y=10 # f1.x=3 # 设置属性的时候会触发——setattr——— class Foo: def __init__(self,name): self.name=name def __getattr__(self, item): print('你找的属性【%s】不存在' %item) def __setattr__(self, k,v): print('执行setattr',k,v) if type(v) is str: print('开始设置') # self.k=v #触发__setattr__ self.__dict__[k]=v.upper() else: print('必须是字符串类型') def __delattr__(self, item): print('不允许删除属性【%s】' %item) # print('执行delattr',item) # del self.item # self.__dict__.pop(item) f1=Foo('alex') # f1.age=18 #触发__setattr__ # print(f1.__dict__) # print(f1.name) # print(f1.age) # print(f1.gender) # print(f1.slary) print(f1.__dict__) del f1.name print(f1.__dict__)

浙公网安备 33010602011771号