最近精神有点顶不住了,感觉做自己喜欢的事情真的是其乐无穷,被电脑砸脸也只是担心电脑和刚才因为走神没看到的东西。前段时间看了一段话,怕忘记了就写在这里吧,与你共勉“值得念念不忘的应该是自己的梦想和心愿,而不是受过的委屈、难过的小事,甚至命运的捉弄”。
感觉最近进入Python学习的心法阶段,都是在将编程概念,但愿后面自己能够接触到一些实际案例。下面我就开始回顾一下自己今天的学习内容。
一、关于多态
多态的概念指出了对象如何通过他们共同的属性和动作来操作及访问,而不需要考虑具体的类,多态表明了动态绑定的存在,
多态实际上是依附于继承的两种含义,“改变”和“扩展”本身意味着必须有机制去自动化选用你改变/扩展的版本,请看下面的案例:
# 首先我们看一下关于Python中已经存在的案例 # 之前我们看到过一个len()方法,针对list、str、tuple都可以使用 a = 'hello' #a是str对象 b = [1,2,3,4] #b是list对象 c = (1,2,3,4) #c是tuple对象 # 然后他们三个都可以使用len()方法 print(len(a)) print(len(b)) print(len(c)) # 以上三个对象属于不同的类,但是他们都可以调用同一个len()方法 # 这其实就是一种多态,但是这只是最基础的状态 # 下面列举一个关于水的案例吧 class H20: def __init__(self,name,temperature): self.name = name self.temperature = temperature def turn_ice(self): if self.temperature < 0 : print('%s结冰了'%self.name) if self.temperature < 100 and self.temperature >= 0 : print('%s是流动的水'%self.name) if self.temperature > 100: print('%s随着气飘走了'%self.name) class Water(H20): pass class Ice(H20): pass class Steam(H20): pass w1 = Water('water',25) i1 = Ice('ice',-23) s1 = Steam('steam',120) w1.turn_ice() i1.turn_ice() s1.turn_ice() # water是流动的水 # ice结冰了 # steam随着气飘走了 # 不同类产生的实例化对象,同时可以调用turn_ice方法,并且产生了不同的结果
类的继承有两层含义:改变/扩展
多态就是类的两层意义的一个具体实现机制,调用不同类的实例对象下的相同方法,实现的过程不一样,Python中的标准类型就是多态的一个很好示范,刚才的len()
二、关于封装
大致是有三个层次的含义
1.类就是麻袋,这本身就是一种封装
2.类中定义私有属性,只有内部使用,外部无法访问(这里有两种方式)
# 首先是第一种形式的封装,就是在你想要封装的变量前面加上'_'单下划线 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._high) # 这种情况下你依旧可以调用,Python中并不做强制要求
或者是以双下划线开头的情况:
# 首先是第一种形式的封装,就是在你想要封装的变量前面加上'_'单下划线 class Room: __picee = '10000/m' 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.__piecee) # 这样直接调用就会报错:'Room' object has no attribute '__piecee' # 如果你认为这样真的不能调用就太天真了 print(Room.__dict__) # {'_Room__picee': '10000/m', '__init__': <function Room.__init__ at 0x0000020FD70840D0>, # '__weakref__': <attribute '__weakref__' of 'Room' objects>, '__module__': '__main__', '__doc__': None, # 'tell_area': <function Room.tell_area at 0x0000020FD7084488>, 'tell_width': <function Room.tell_width at 0x0000020FD7084510>, # '__dict__': <attribute '__dict__' of 'Room' objects>} # 你会在属性字典中发现'_Room__picee': '10000/m' # 其实你不能直接调用的本质是Python帮你自动修改了变量名称 # 所以 print(r1._Room__picee) # 最终还是能显示的
3.第三个层面的封装,明确区分内外,内部的实现逻辑,外部无法知晓,并且为封装到内部的逻辑提供一个间接访问接口供外部使用(这才是真正的封装)
# 首先是第一种形式的封装,就是在你想要封装的变量前面加上'_'单下划线 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 room = Room('卫生间', 'alex', 100, 100, 10000) r1= room # arear=r1.__width * r1.__length print(r1.tell_area())
内容总结:
1.通过封装明确内外,我们作为类的缔造者,如何造的逻辑你无需知道,我们想让你知道你才能知道,明确的划分等级,调用者直管用
2.通过继承+多态在语言层面支持了归一化设计
好困好困,我睡了