面向对象是为了能够更好的维护更新我们的程序而存在的,数据工厂一样开发过程,站在上帝的角度考虑,
我们看到的是就好像是一个列表a = [ 1, 2] ,这个列表有什么功能,这些是内置的,而我们可以同创造出这
样的一个列表,同时列表的功能有我们自由决定,如何俩狗实现高度的自由,这就是这篇文章要解释 的,
关于面向对象的特性封装,通过封装可以达到自已的控制类的特性,你就是真正的主宰,看如下代码演示:
封装的真谛在于明确地区分内外,封装的属性可以直接在内部使用,而不能被外部直接使用,然而定义属性的目的终归是要用,外部要想用类隐藏的属性,需要我们为其开辟接口,让外部能够间接地用到我们隐藏起来的属性,那这么做的意义何在???
1:封装数据:将数据隐藏起来这不是目的。隐藏起来然后对外提供操作该数据的接口,然后我们可以在接口附加上对该数据操作的限制,以此完成对数据属性操作的严格控制。
classTeacher:def __init__(self,name,age):#self.__name=name
#self.__age=age
self.set_info(name,age)deftell_info(self):print('姓名:%s,年龄:%s' %(self.__name,self.__age))defset_info(self,name,age):if notisinstance(name,str):raise TypeError('姓名必须是字符串类型')if notisinstance(age,int):raise TypeError('年龄必须是整型')
self.__name=name
self.__age=age
t=Teacher('egon',18)
t.tell_info()
t.set_info('egon',19)
t.tell_info()
面向对象的 特性 什么是特性property
相当于制造一个伪装饰器
class People:
def __init__(self,name, weight, height):
self.name = name
self.weight = weight
self.height = height
@property
def bmi(self):
return self.weight / (self.height **2)
albert = People('albert',63,1.65)
drama = People('drama',49,1.71)
print(albert.bmi)
print(drama.bmi)
为什么要用property
将一个类的函数定义成特性以后,对象再去使用的时候obj.name,根本无法察觉自己的name是执行了一个函数然后计算出来的,这种特性的使用方式遵循了统一访问的原则
除此之外,看下
ps:面向对象的封装有三种方式:
【public】
这种其实就是不封装,是对外公开的
【protected】
这种封装方式对外不公开,但对朋友(friend)或者子类(形象的说法是“儿子”,但我不知道为什么大家 不说“女儿”,就像“parent”本来是“父母”的意思,但中文都是叫“父类”)公开
【private】
这种封装对谁都不公开
python并没有在语法上把它们三个内建到自己的class机制中,在C++里一般会将所有的所有的数据都设置为私有的,然后提供set和get方法(接口)去设置和获取,在python中通过property方法可以实现
class Foo:
def __init__(self,val):
self.__NAME=val #将所有的数据属性都隐藏起来
@property
def name(self):
return self.__NAME #obj.name访问的是self.__NAME(这也是真实值的存放位置)
@name.setter
def name(self,value):
if not isinstance(value,str): #在设定值之前进行类型检查
raise TypeError('%s must be str' %value)
self.__NAME=value #通过类型检查后,将值value存放到真实的位置self.__NAME
@name.deleter
def name(self):
raise TypeError('Can not delete')
f=Foo('egon')
print(f.name)
# f.name=10 #抛出异常'TypeError: 10 must be str'
del f.name #抛出异常'TypeError: Can not delete'
@property可以将python定义的函数“当做”属性访问,从而提供更加友好访问方式,但是有时候setter/deleter也是需要的。
1》只有@property表示只读。
2》同时有@property和@x.setter表示可读可写。
3》同时有@property和@x.setter和@x.deleter表示可读可写可删除。
[python] view plain copyclass student(object): #新式类
def __init__(self,id):
self.__id=id
@property#读
defscore(self):returnself._score
@score.setter#写
defscore(self,value):if notisinstance(value,int):raise ValueError('score must be an integer!')if value<0 or value>100:raise ValueError('score must between 0 and 100')
self._score=value
@property#读(只能读,不能写)
defget_id(self):return self.__ids=student('123456')
s.score=60 #写
print s.score #读#s.score=-2 #ValueError: score must between 0 and 100#s.score=32.6 #ValueError: score must be an integer!
s.score=100 #写
print s.score #读
print s.get_id #读(只能读,不可写)#s.get_id=456 #只能读,不可写:AttributeError: can't set attribute
运行结果:
60
100
123456
1 什么是多态
多态指的是同一种事物多种形态
2、为什要用多态
用基类创建一套统一的规则,强制子类去遵循(使用抽象类实现),这样便可以
在不用考虑对象具体类型的前提下而直接使用对象下的方法
3、如何用多态
importabcclass Animal(metaclass=abc.ABCMeta):
@abc.abstractmethoddefeat(self):pass@abc.abstractmethoddefdrink(self):pass@abc.abstractmethoddefrun(self):pass
classCat(Animal):defeat(self):print('cat eat')defdrink(self):print('cat drink')defrun(self):print('cat run')defbark(self):print('喵喵喵')#obj=Animal() # 抽象基类本身不能被实例化
classCat(Animal):defeat(self):print('cat eat')defdrink(self):print('cat drink')defrun(self):print('cat run')defbark(self):print('喵喵喵')
c=Cat()
c.BARK()
len函数的原理
s='hello'l=[1,2,3]
t=(4,5,6)
s.__len__()
l.__len__()
t.__len__()#def LEN(obj):#return obj.__len__()#print(LEN(s))print(LEN(l))print(LEN(t))print(len(l))print(len(s))print(len(t))
鸭子类型
classFoo:deff1(self):print('from foo.f1')deff2(self):print('from foo.f2')classBar:deff1(self):print('from bar.f1')deff2(self):print('from bar.f2')
obj1=Foo()
obj2=Bar()
obj1.f1()
obj1.f2()
obj2.f1()
obj2.f2()classDisk:defread(self):print('disk read')defwrite(self):print('disk write')classTxt:defread(self):print('txt read')defwrite(self):print('txt write')classProcess:defread(self):print('process read')defwrite(self):print('process write')
obj1=Disk()
obj2=Txt()
obj3=Process()
obj1.read()
obj2.read()
obj3.read()
绑定方法:
在类内部定义的函数,默认就是给对象来用,而且是绑定给对象用的,称为对象的绑定方法
绑定对象的方法特殊之处:
应该由对象来调用,对象来调用,会自动将对象当作第一个参数传入
绑定到类的方法特殊之处:
应该由类来调用,类来调用,会自动将类当作第一个参数传入
staticmethod:非绑定方法,就是一个普通函数
#特性:既不跟类绑定,也不跟对象绑定,这意味着谁都能用
#谁来用都是一个普通函数,也就是说没有自动传值的特性了
classmethod:类的调用
importsettingsimporthashlibimporttimeclassPeople:def __init__(self,name,age):
self.uid=self.create_id()
self.name=name
self.age=agedeftell(self):print('%s: %s:%s' %(self.uid,self.name,self.age))
@classmethoddeffrom_conf(cls):returncls(settings.NAME,settings.AGE)
@staticmethoddefcreate_id():
m=hashlib.md5()
m.update(str(time.clock()).encode('utf-8'))returnm.hexdigest()
obj=People('egon',18)
print(obj.create_id())
print(People.create_id())