类的进阶
一.类的存储与实例对象的存储
类定义好后会为类开辟一块空间。
实例化一个类后会将初始化的数据和对象名一并传入类中,并在类的外面开辟一块空间用于存数据。
注意:初始化时会将对象当形参(self)传入类
实例对象不会将类中共同的方法或变量的存下来,而是通过self进行访问。
二.变量的分类
实例属性(静态属性)只对该实例对象有作用域
实例方法(动态属性)只对该实例对象有作用域
类变量 对所有的实例对象都有作用域,只存放在类里面
注意:当类变量与实例变量矛盾时,实例变量有效,通过实例改类变量时,是将类变量复制一份到该实例对象中 ,将复制后的进行修改。但list不一样,通过实例改类变量的list时就是在类中修改。
二.构造函数
class Dog: def __init__(self,name,age,salary): self.name = name self.age = age self.salary = salary#等号的左右的名称可以不同,左边是属性名,右边是形参名 def bulk(self,voice) print('%s is bulking,,,,%s' %s(self.name,voice)) def __del__(): print('我是析构函数') taidi = Dog(taidi,3,2300) taidi.bulk()
作用:实例化类时,进行初始化,并开辟一块空间。但不会将类中的方法都复制一边
实例化类时构造函数会自动执行
三.析构函数
但不能有参数,实例释放和销毁时自动执行,进行扫尾工作,如关闭数据库链接。
四.私有属性,私有方法
私有属性或方法名前加 __(双下划线)外部不能访问,但可以通过类中其他的方法访问。
五.继承
在构造一个类时将要继承的父类当做参数传入。
class school_member(object): #父类,object是基类,是新式类的写法 def __init__(self,name,age,id): self.name=name self.age=age self.id=id def enroll(self): #注册函数 print('welcom to %s"%self.name) class student(school_member): def __init__(self,name,age,id,money): #school_member.__init__(self,name,age,id) super(sudent,self).__init__(name,age,id) self.money=money
六.多继承
多继承的顺序,分为广度优先和深度优先
Python3中新式类和经典类都是广度优先
Python2中 新式类是广度优先 经典类是深度优先
class A(object): def __init__(self): print('A') class B(A): def __init__(self): print('B') class C(A): def __init__(self): print('C') class D(B,C): def __init__(self): print('D')
说明:B,C继承了A,而D继承B,C
广度优先:先在B中找有没有构造函数,没有再在C中找,最后在A中找
深度优先:在B中找没有再再A中找,后面依次类推。
多继承的顺序是按参数从左向右。并依次寻找是否有构造函数,有了就不执行后面的构造函数,前面构造的属性,可以在另一个父类中调用。
class School(object): def __init__(self,name,addr): self.name=name self.addr=addr self.students=[] self.teachers=[] self.couses=[] self.greens=[] def encoll(self,stu_obj): self.students.append(stu_obj) print("欢迎%s来到%s"%(stu_obj.name,self.name)) def hair(self,teacher_obj): self.teachers.append(teacher_obj) def couse(self,cou_obj): self.couses.append(cou_obj) def green(self,gren_obj): self.greens.append(gren_obj) class Sch_member(object): def __init__(self,name,sex,age): self.name=name self.sex=sex self.age = age class Teacher(Sch_member): def __init__(self,name,sex,age,salary,couse_obj,green_obj,id,sch_obj): super(Teacher, self).__init__(name.sex,age) self.salary=salary self.couse=couse self.green=green self.id=id self.school=sch_obj def teach(self): print("%s teaching the class %s of %s"%s(self.name,self.green,self.couse)) class Student(Sch_member): def __init__(self,name,sex,age,id,green_obj,sch_obj): # type: (object, object, object, object, object, object) -> object super(Student,self).__init__(name,sex,age) self.id=id self.green=green_obj self.school=sch_obj def choose_couse(self,name,addr,name1,teacher_obj,time,priser,green_obj): print("请选择课程") self.couses.append(Couse(name,addr,name1,teacher_obj,time,priser,green_obj)) class green(School): def __init__(self,name,addr,name1,teacher_obj,couse_obj): super(green, self).__init__(name,addr) self.teacher=teacher_obj self.couse=couse_obj class Couse(School): def __init__(self,name,addr,name1,teacher_obj,time,priser,green_obj): self.name=name1 super(Couse, self).__init__(name,addr) self.teacher=teacher_obj self.time=time self.priser=priser self.green=green_obj B_sch=School("Beijing universtry","beijing") S_sch=School("fudan universtry","shanghai") g_01=green("Beijing universtry","beijing","苹果班",teacher1,c_language) B_sch.green(g_01) g_02=green("fudan universtry","shanghai","仙女班",teacher2,python) S_sch.green(g_01) c_language=Couse("Beijing universtry","beijing","c",teacher1,"8:00-12:00",12000,g_01) B_sch.green(c) python=Couse("fudan universtry","shanghai","Python",teacher2,"8:00-12:00",12000,g_02) S_sch.green(python) teacher1=Teacher("alex","男",22,21000,c_language,g_01,1001,B_sch) B_sch.hair(teacher1) teacher2=Teacher("oldboy","男",32,41000,python,g_02,10002,S_sch) S_sch.hair(teacher2) '''stu1 = Student("xiaoling","男",23,0001,g_01,B_sch) B_sch.encoll(stu1) stu2 = Student("hanshangyan","女",23,0002,g_02,S_sch) S_sch.encoll(stu2)'''
七.多态
一个接口,多个实现,即通过一个接口的调用实现多个功能
class animal(object): def __init__(self,name,age) self.name = name self.age = age def eat(self): print("%s is eating %s"%(self.name,sself.food)) '''多态的实现''' @staiticmethod def animal_food(obj): obj.eat() class Dog(animal): def __init__(self,name,age,food) super(Dog,self).__init__(name,age) self.food = food d1=Dog(taidi,2,bone) d2 = Dog(bianmu,3,chiken) animal.eat(d1) animal.eat(d2)
八.静态方法,类方法,属性方法
1.静态方法 @staticmethod
名义上是类的方法,但与类没有什么联系,除了必须要通过类的实例调用,但该方法不能调用类或实例中的任何属性,同时它可以没有参数,正常的方法必须至少有一个self参数
2.类方法 @classmethod
只能访问类的变量,不能访问实例属性
3.属性方法 @porperty
将一个方法函数变成属性,同时可以通过@方法名.setter进行设置 用@方法名.deltter进行删除属性,(设置属性的本质是在类属性一开始写好,但不传参,通过该方法进行传参),
class perpol(object): n= "i am class var" def __init__(self,name): self.name = name self.__food @staticmethod def test1(): print("in the static") @porperty def eat(self): print("%s is eating %s"%(self.name,self.__food)) @eat.setter def eat(self,food): print("set porperty done") self.__food = food @eat.deltter def eat(self): del self.__food p1 =perpol("alex",23) p1.test1() p1.eat p1.eat = "包子"#进行属性设置时自动调用 del p1.eat#进行删除操作时自动执行上面的函数
九.各种内置方法
1.__dict__
返回所有的方法与属性,当是类名时返回类中的属性与方法,若是实例时返回值实例的 属性
2.__module__/__class__
__module__ 返回导入该类对应的模块
__class__ 返回模块和类名(路径)
3.__setitem__/getitem__/__delitem__
给类添加字典的功能,
class Foo(object): def __init__(self,name): self.name=name self.date={} def __setitem__(self,key,value): print(have set done) self.date[key]= value def __getitem__(self,key): print(self.date[key]) def __delitem__(self,key): del self.date[key] f=Foo('alex') f[age]=23#自动调用__setitem__ print(f[age])#调用__getitem__
4.__doc__
打印类名时会打印出注释语句
5.__str__
打印实例名时会打印改函数的返回值,用于了解实例对象
6.__call__
class Foo(object): def __call__(self): print(in the call) f=Foo() f()#在实名后加括号调用call函数
在类后面加括号自动执行__init__,在实例名后加括号自动执行__call__
类的类是type
通过type方法来定义一个类,将没有关系的函数通过type联系起来了
def __init__(self,name,age): self.name=name self.age=age def information(self): print('the name is',name) Foo=type('Foo',(object,),{'__init__':__init__, 'fanc':information}) f=Foo('高佳雪',20) f.information()
7.__metaclass__ 类中的一个属性__metaclass__表示该类由谁实例化创建,因此可以为__metaclass__设置一个type类的派生类
class MyType(type): def __init__(self,what,bases=None,dict=None): surper(MyType,self).__init__(what,bases,dict) def __call__(self,*args,**kwargs): obj=self.__new__(self,*args,**kwargs) self.__init__(obj) class Foo(object): __metaclass__ = MyType def __init__(self,name): self.name=name def __new__(cls,*args,**kwargs):#cls是MyType中的obj return object.__new__(cls,*agrs,**kwargs) obj = Foo()
类的实例实际是通过__new__方法创建的self就是__new__函数的返回值,即为实例开辟的一块空间
十.反射
通过字符串映射或修改程序运行时的状态,属性,方法
1.getattr( object, name, default=none ) 根据字符串获取obj对象里对应的方法的内存地址
2.hasattr( object, name_str ) 判断一个对象object里是否有对应的name_str字符串对应的属性或方法
3.setattr(x ,y ,v) x是实例对象,y是字符串名,v是方法或属性
4.delattr(x, y ) x,y同上
class Foo(object): def __init__(self,name): self.name=name f = Foo('alex') def bulk(self): print('%s is bulking',%self.name) choice = input("输入方法或属性").strip() if hasatter(f,choice): getatter(f,choice)#如果是方法可以改为 choice = getatter(f,choice) choice(f) else: setatter(f,choice,bulk)#f.choice=bulk func = getatter(f,choice) func(f)