一.1.关于类:
在python3中,所有类都是新式类
class A:pass
print(A.__bases__) 查看方法
3中不用写默认都是继承object 类
在python2中,新式类
class B(object):pass
class C(B):pass
所以2中必须说明父类是abject才是新式类
在python2中,经典类
class D:pass
print(D.__bases__) 查看方法
在python2里,如果不说明父类的话这个类本身就是经典类。
2.类的属性:
类的变量和类的函数都属于类的属性
二.继承
新式类的继承原理:
所有的新式类的查找顺序:广度优先
python2中经典类继承:
查找属性时遵循:深度优先。注意经典类里没有MRO这个方法。
***为了实现继承,python会在MRO列表上从左到右开始查找基类,直到找到第一个匹配这个属性的类为止。
而这个MRO列表的构造是通过一个C3线性化算法来实现的。我们不去深究这个算法的数学原理,它实际上就是合并所有父类的MRO列表并遵循如下三条准则:
1.子类会先于父类被检查
2.多个父类会根据它们在列表中的顺序被检查
3.如果对下一个类存在两个合法的选择,选择第一个父类
三.super用法:
super在python2中的用法:
1.super(自己的类名,self).父类的函数名字
2.super只能用于新式类
python3 里都是新式类
1.super(),括号内默认,不用写,也可以自己再写上
四.多态和多态性:
多态:同一种事物的多种形态,动物分为人类,猪类(在定义角度)
多态性:一种调用方式,不同的执行效果(多态性)
多态性是指具有不同功能的函数可以使用相同的函数名,这样就可以用一个函数名调用不同内容的函数。
在面向对象方法中一般是这样表述多态性:向不同的对象发送同一条消息,不同的对象在接收时会产
生不同的行为(即方法)。也就是说,每个对象可以用自己的方式去响应共同的消息。所谓消息,就是
调用函数,不同的行为就是指不同的实现,即执行不同的函数。
综上我们也可以说,多态性是‘一个接口(函数func),多种实现(如f.click())’
五.封装:
封装数据的主要原因是:保护隐私 和 隔离复杂度。
1.封装的应用方法:
property:是一种特殊的属性,访问它时会执行一段功能(函数)然后返回值
2.为什么要用property
将一个类的函数定义成特性以后,对象再去使用的时候obj.name,
根本无法察觉自己的name是执行了一个函数然后计算出来的,这种特性的使用方式遵循了统一访问的原则
***被property装饰的属性会优先于对象的属性被使用***
--其实就是把用户真正想操作的数据转移到了property下面的函数里。--
#而被propery装饰的属性,如name,分成三种:
# 1.property
# 2.name.setter
# 3.name.deleter
2.面向对象的封装有三种方式:
【public】
这种其实就是不封装,是对外公开的
【protected】
这种封装方式对外不公开,但对朋友(friend)或者子类(形象的说法是“儿子”,但我不知道为什么大家 不说“女儿”,就像“parent”本来是“父母”的意思,但中文都是叫“父类”)公开
【private】
这种封装对谁都不公开
3.python并没有在语法上把它们三个内建到自己的class机制中,在C++里一般会将所有的所有的数据都设置为私有的,
然后提供set和get方法(接口)去设置和获取,在python中通过property方法可以实现。
3.封装的好处:
封装在于明确区分内外,使得类实现者可以修改封装内的东西而不影响外部调用者的代码;而外部使用用者只知道一个接口(函数),
只要接口(函数)名、参数不变,使用者的代码永远无需改变。这就提供一个良好的合作基础——或者说,只要接口这个基础约定不变,则代码改变不足为虑
4.静态方法和类方法
通常情况下,在类中定义的所有函数(注意了,这里说的就是所有,跟self啥的没关系,self也只是一个再普通不过的参数而已)都是对象的绑定方法,
对象在调用绑定方法时会自动将自己作为参数传递给方法的第一个参数。除此之外还有两种常见的方法:静态方法和类方法,二者是为类量身定制的,但是实例非要使用,也不会报错,后续将介绍。
1 静态方法:staticmethod 就是类的的工具包。
是一种普通函数,位于类定义的命名空间中,不会对任何实例类型进行操作,python为我们内置了函数staticmethod来把类中的函数定义成静态方法
没有@staticmethod:
但凡是定义在类的内部,并且没有被任何装饰器修饰过的方法,都是绑定方法:有自动传值功能
有@staticmethod:
但凡是定义在类的内部,并且被staticmethod装饰器修饰过的方法,都是解除绑定的方法函数,实际上在类内部定义的普通函数:所以它也就没有自动传值功能了
2.类方法
类方法是给类用的,类在使用时会将类本身当做参数传给类方法的第一个参数,python为我们内置了函数classmethod来把类中的函数定义成类方法
实质:把一个方法绑定给类:类.绑定到类的方法(),会把类本身当做第一个参数自动传给绑定到类的方法
六。使用方法:1. __str__的用法
#__str__定义在类内部,必须返回一个字符串类型, #什么时候会出发它的执行呢?打印由这个类产生的对象时,会触发执行 class People: def __init__(self,name,age): self.name=name self.age=age def __str__(self): return '<name:%s,age:%s>' %(self.name,self.age) p1=People('egon',18) print(p1) str(p1) #----->p1.__str__()
2.classmethod的用法
1 # class Foo: 2 # def bar(self): 3 # pass 4 # @classmethod #把一个方法绑定给类:类.绑定到类的方法(),会把类本身当做第一个参数自动传给绑定到类的方法 5 # def test(cls,x): 6 # print(cls,x) #拿掉一个类的内存地址后,就可以实例化或者引用类的属性了 7 # 8 # 9 # # print(Foo.bar) 10 # # print(Foo.test) 11 # 12 # Foo.test(123123) 13 # 14 # f=Foo() 15 # print(f.bar) 16 # print(f.test) 17 # print(Foo.test) 18 # f.test(1111) 19 20 import time 21 class Date: 22 def __init__(self,year,month,day): 23 self.year=year 24 self.month=month 25 self.day=day 26 # 27 # def test(): 28 # print('from test') 29 # 30 @classmethod 31 def now(cls): #用Date.now()的形式去产生实例,该实例用的是当前时间 32 print(cls) 33 t=time.localtime() #获取结构化的时间格式 34 obj=cls(t.tm_year,t.tm_mon,t.tm_mday) #新建实例并且返回 35 return obj 36 37 @classmethod 38 def tomorrow(cls):#用Date.tomorrow()的形式去产生实例,该实例用的是明天的时间 39 t=time.localtime(time.time()+86400) 40 return cls(t.tm_year,t.tm_mon,t.tm_mday) 41 42 43 class EuroDate(Date): 44 def __str__(self): 45 return '年:%s,月:%s,日:%s' %(self.year,self.month,self.day) 46 47 # e1=EuroDate.now() 48 # print(e1) 49 50 e1=EuroDate(1,1,1) 51 print(e1)
3.property属性的用法
1 # import math 2 # class Circle: 3 # def __init__(self,radius): #圆的半径radius 4 # self.radius=radius 5 # 6 # @property #area=property(area) 7 # def area(self): 8 # return math.pi * self.radius**2 #计算面积 9 # 10 # @property 11 # def perimeter(self): 12 # return 2*math.pi*self.radius #计算周长 13 14 # c=Circle(7) 15 # print(c.radius) 16 # c.radius=10 17 # 18 # # print(c.area()) 19 # # print(c.perimeter()) 20 # print(c.area) 21 # print(c.perimeter) 22 23 class People: 24 def __init__(self,name,age,height,weight): 25 self.name=name 26 self.age=age 27 self.height=height 28 self.weight=weight 29 @property 30 def bodyindex(self): 31 return self.weight/(self.height**2) 32 33 # p1=People('cobila',38,1.65,74) 34 # print(p1.bodyindex) 35 # p1.weight=200 36 # print(p1.bodyindex) 37 38 #被property装饰的属性会优先于对象的属性被使用 39 40 #而被propery装饰的属性,如sex,分成三种: 41 # 1.property 42 # 2.sex.setter 43 # 3.sex.deleter 44 45 # class People: 46 # def __init__(self,name,SEX): 47 # self.name=name 48 # # self.__sex=SEX 49 # self.sex=SEX #self.sex='male' p1.sex='male' 50 # @property 51 # def sex(self): 52 # return self.__sex #p1.__sex 53 # 54 # @sex.setter 55 # def sex(self,value): 56 # # print(self,value) 57 # if not isinstance(value,str): 58 # raise TypeError('性别必须是字符串类型') 59 # self.__sex=value #p1.__sex='male' 60 # @sex.deleter 61 # def sex(self): 62 # del self.__sex #del p1.__sex 63 64 # p1=People('cobila','male') 65 # print(p1.tell_name()) 66 # 67 # print(p1.sex) 68 # p1.sex='123' 69 70 # p1.sex='female' 71 # print(p1.sex) 72 73 # p1.sex=123123123123123123123123123213 74 75 # p1=People('cobila',123123123123123) 76 # p1=People('cobila','male') 77 # print(p1.sex) 78 # del p1.sex #del self.sex 79 # print(p1.sex)
4.staticmethod的用法
1 # class Foo: 2 # def spam(self): 3 # print('----->',self) 4 5 # Foo.spam(123123) 6 7 # f1=Foo() 8 # f1.spam() 9 10 # class Foo: 11 # @staticmethod 12 # def spam(x,y,z): 13 # print(x,y,z) 14 # 15 # 16 # # Foo.spam(1,2,3) 17 # f2=Foo() 18 # f2.spam(1,2,3) 19 import time 20 class Date: 21 def __init__(self,year,month,day): 22 self.year=year 23 self.month=month 24 self.day=day 25 # 26 # def test(): 27 # print('from test') 28 # 29 @staticmethod 30 def now(): #用Date.now()的形式去产生实例,该实例用的是当前时间 31 t=time.localtime() #获取结构化的时间格式 32 obj=Date(t.tm_year,t.tm_mon,t.tm_mday) #新建实例并且返回 33 return obj 34 35 @staticmethod 36 def tomorrow():#用Date.tomorrow()的形式去产生实例,该实例用的是明天的时间 37 t=time.localtime(time.time()+86400) 38 return Date(t.tm_year,t.tm_mon,t.tm_mday) 39 # d1=Date(2017,1,13) 40 # # Date.test() 41 # print(d1.test) 42 # d1.test() 43 44 # d1=Date(2017,1,13) 45 # d2=Date(2017,1,14) 46 # date_now=Date.now() 47 # print(date_now) 48 # print(date_now.year) 49 # print(date_now.month) 50 # print(date_now.day) 51 52 # d1=Date.now() 53 # print(d1.year,d1.month,d1.day) 54 55 # d2=Date.tomorrow() 56 # print(d2.day) 57 58 #但凡是定义在类的内部,并且没有被任何装饰器修饰过的方法,都是绑定方法:有自动传值功能 59 d1=Date(1212,22,22) 60 print(d1.now) 61 print(Date.now) 62 # d1.now() #now(d1) 63 64 #但凡是定义在类的内部,并且被staticmethod装饰器修饰过的方法,都是解除绑定的方法,实际上就函数:就没有自动传值功能了 65 d_n1=Date.now() 66 d_n2=d1.now() 67 print(d_n1.year,d_n1.month,d_n1.day) 68 print(d_n2.year,d_n2.month,d_n2.day)