一、类的相关知识
类:把一类事物具有相同特征和动作整合到一起
对象:基于类而创建的一个具体的实例
实例化:类生成对象的过程
关键字 class 类名:
类的文档字符串
类体
python2 中python class类名 是经典类
class类名(object) 是新式类
python3中都是新式类
类的属性:
数据属性、函数属性
都存在类的属性字典中—
实例:只有数据属性
用.的方式访问就是类属性或实例属性
1 class School: 2 '''这是一个学校类''' #类的文档字符串 3 number =100 #类的数据属性 4 def __init__(self,name,addr,type): 5 #初始化构造函数 6 self.name = name #self.name 存在实例的属性字典中,name是key 后面的name是传入的变量 7 self.addr = addr 8 self.type = type 9 def create_exam(self): 10 print("%s%s正在举行考试"%(self.type,self.name)) 11 s1 = School("Ezhizen","中国","私立") #实例化一个对象 12 # print(s1) 13 print(School.number) 14 print(School.__dict__) 15 School.x = 10#添加类数据属性 16 print(School.__dict__) 17 del School.x #删除类属性 18 print(School.__dict__) 19 def zhao_sheng(self): 20 print("%s%s正在招生"%(self.type,self.name)) 21 School.zhao = zhao_sheng #添加类的函数属性 22 print(School.__dict__) #类的属性字典 23 print(s1.__dict__) #字典的属性字典 24 s1.create_exam() 25 School.zhao(s1) #类调用方法时要把实例传进去 26 print(s1.name)
1 class Person: 2 number = 10 3 def __init__(self,name,age,sex): 4 self.name = name 5 self.age= age 6 self.sex = sex 7 @property #静态属性 8 def learn(self): 9 print("%s正在学python"%self.name) 10 11 def play_ball(self,ball): 12 print("%s正在打%s"%(self.name,ball)) 13 @classmethod #类方法 14 def run(cls): 15 print(cls.number) 16 @staticmethod #静态方法 17 def test(a): 18 print(a) 19 p1 = Person("Ezhizen",18,"boy") 20 # p1.learn() 21 p1.learn #当函数变成静态属性时,运行函数不需要加(),就可以封装逻辑 22 Person.run() #不跟实例捆绑,只跟类捆绑 23 p1.run() #但实例也可以调用 24 Person.test(10) #静态方法,类调用,实例不能调用。只是名义上归类管理,不能使用类变量和实例变量,是类的工具包 25 26 #普通方法:由对象调用;至少一个self参数;执行普通方法时,自动将调用该方法的对象赋值给self; 27 #类方法:由类调用; 至少一个cls参数;执行类方法时,自动将调用该方法的类复制给cls; 28 #静态方法:由类调用;无默认参数;
1 class Coat: 2 def __init__(self): 3 #原价 4 self.original_price = 100 5 #折扣 6 self.discout = 0.7 7 @property 8 def price(self): 9 new_price = self.original_price*self.discout 10 return new_price 11 @price.setter 12 def price(self,value): 13 self.original_price=value 14 print("11") 15 @price.deleter 16 def price(self): 17 del self.original_price 18 print(222) 19 c1 = Coat() 20 new_price = c1.price #获得商品价格 21 print(new_price) 22 c1.price = 80 #修改商品价格 23 del c1.price #删除商品价格
1 import time 2 class Date: 3 def __init__(self,year,month,day): 4 self.year=year 5 self.month=month 6 self.day=day 7 @staticmethod 8 def now(): 9 t=time.localtime() 10 return Date(t.tm_year,t.tm_mon,t.tm_mday) 11 12 class EuroDate(Date): 13 def __str__(self): 14 return 'year:%s month:%s day:%s' %(self.year,self.month,self.day) 15 16 e=EuroDate.now() 17 print(e) #我们的意图 18 import time 19 class Date: 20 def __init__(self,year,month,day): 21 self.year=year 22 self.month=month 23 self.day=day 24 # @staticmethod 25 # def now(): 26 # t=time.localtime() 27 # return Date(t.tm_year,t.tm_mon,t.tm_mday) 28 29 @classmethod #改成类方法 30 def now(cls): 31 t=time.localtime() 32 return cls(t.tm_year,t.tm_mon,t.tm_mday) #哪个类来调用,即用哪个类cls来实例化 33 34 class EuroDate(Date): 35 def __str__(self): 36 return 'year:%s month:%s day:%s' %(self.year,self.month,self.day) 37 38 e=EuroDate.now() 39 print(e) #我们的意图是想触发EuroDate.__str__,此时e就是由EuroDate产生的,所以会如我们所愿
组合:一个类中存在另一个类,而且是他的组成部分
1 class School: 2 def __init__(self,name,addr): 3 self.name = name 4 self.addr = addr 5 6 class Course: 7 def __init__(self,name,price,school): 8 self.name = name 9 self.price = price 10 self.school = school 11 12 s1 = School("Ryoma School","China") 13 c1 = Course("python",1500,s1) 14 print(c1.school.name)
二、面向对象的三大特性1.封装2.多态3.继承
1.继承
继承是一种创建新类的一种方式,新建的类可以继承一个或多个父类(多继承),父类可以称为基类或超类,新建的类可以称为子类或派生类。
class A: '''我是A类''' pass class B(A): '''我是B类''' pass print(A.__bases__) #查看基类 print(B.__bases__) print(A.__name__) #查看类名 print(A.__doc__) #查看文档 print(A.__module__) #__main__ print(A.__class__) #type
1 class Vehicles: 2 def __init__(self,name,power,num): 3 self.name= name 4 self.power = power 5 self.num = num 6 def run(self): 7 print("%s开动了"%self.name) 8 class Railway(Vehicles): 9 def __init__(self,name,power,num,s): 10 #子类调用父类的构造函数 11 # super().__init__(name,power,num) 12 super(Railway,self).__init__(name,power,num) 13 # Vehicles.__init__(self,name,power,num) 14 self.s = s 15 def run(self): 16 #在子类中自己定义run函数 17 print("%s%s开动了"%(self.power,self.name)) 18 rail = Railway("Ezhizen","氢能",100000,15000) 19 rail.run()
当类之间有明显的不同,而且较小的类是较大类的的一个组成部分,用组合比较好
当类之间存在很大的相同,提取它们公共的部分做成基类,用继承
接口继承
定义一个类 ,提供接口函数,子类继承,去实现该方法。归一化设计。 不需要关心类是什么,只需要知道哪些功能
class Interface: def read(self): #定义接口函数 pass def write(self): #定义接口函数 # pass class Tex(Interface): def read(self): #实现接口函数 print("文本读") def write(self): #实现接口函数 print("文本写") class Sata(Interface): #磁盘,具体实现read和write def read(self): print('硬盘数据的读取方法') def write(self): print('硬盘数据的读取方法') class Process(Interface): def read(self): print('进程数据的读取方法') def write(self): print('进程数据的读取方法')
经典类中,继承顺序:深度优先. 新式类中 广度优先
1 class A: 2 def test(self): 3 print("in A") 4 class B(A): 5 # def test(self): 6 # print("in B") 7 pass 8 class C(A): 9 # def test(self): 10 # print("in C") 11 pass 12 class D(B): 13 # def test(self): 14 # print("in D") 15 pass 16 class E(C): 17 # def test(self): 18 # print("in E") 19 pass 20 class F(D,E): 21 # def test(self): 22 # print("in F") 23 pass 24 f = F() 25 f.test() #F-D-B-E-C-A #新式类中广度优先 经典类中深度优先 26 print(F.__mro__) #查看继承顺序
2.多态
不同类得到的实例化对象,调用同一种方法
1 import abc 2 class Animal(metaclass=abc.ABCMeta): 3 @abc.abstractmethod 4 def talk(self): 5 pass 6 class Dog(Animal): 7 def talk(self): 8 print("talk") 9 pass 10 class Pig(Animal): 11 def talk(self): 12 print("ddd") 13 Dog() 14 Pig()
1 import abc 2 class Animal(metaclass=abc.ABCMeta): 3 @abc.abstractmethod 4 def talk(self): 5 pass 6 class Dog(Animal): 7 def talk(self): 8 print("talk1") 9 pass 10 class Pig(Animal): 11 def talk(self): 12 print("talk2") 13 class Bird(Animal): 14 def talk(self): 15 print("talk3") 16 d1 = Dog() 17 p1 = Pig() 18 b1 = Bird() 19 d1.talk() #调用同一个方法 20 p1.talk() 21 b1.talk() 22 23 def run(obj): 24 obj.talk() 25 run(d1) #多态 不同类的实例对象调用同一个方法 26 run(p1) 27 run(b1)
3.封装
-单下划线 被隐藏起来的属性,外部不能调用,只是一种约定(私有属性)一般非公共名称用单下划线
__双下划线 私有属性,外部无法调用,只是一种约定.可以通过_类名__属性访问 如 a._P__b 如果涉及到子类,并且有些内部属性应该在子类中隐藏起来。 在继承中,父类如果不想让子类覆盖自己的方法,可以将方法定义为私有的
封装 明确区分内外,内部实现逻辑,外部无法知晓,并且为限制到内部的逻辑提供一个接口给外部使用.
私有属性在import * 时不能运行 但导入具体方法时可以运行
1 __import__("m1.t") #导入顶层m1模块 2 import importlib 3 importlib.import_module("m1.t") #导入底层t模块
1 class Room: 2 def __init__(self,name,length,width,height): 3 self.name = name 4 self.length = length 5 self.width = width 6 self.height = height 7 def show_area(self): 8 return self.length * self.width 9 10 r1 = Room("Ezhizen",12,12,12) 11 area = r1.show_area() 12 print("Ezhizen住的面积",area) 13 class Room: 14 def __init__(self,name,length,width,height): 15 self.name = name 16 self.__length = length 17 self.__width = width 18 self.height = height 19 def __show_area(self): 20 return self.__length * self.__width 21 def show_area(self): 22 #提供接口函数 23 return self.__show_area() 24 r1 = Room("Ezhizen",12,12,12) 25 r1.show_area() 26 print("Ezhizen住的面积",area)
4.自省/反射
1 class A: 2 pass 3 a = A() 4 print(isinstance(a,A)) #判断a是否是A的对象 5 class B(A): 6 pass 7 8 print(issubclass(B,A)) #判断B是否为A的子类
自省:主要是指程序可以访问、检测和修改它本身状态或行为的一种能力.通过字符串的形式操作对象相关的属性
hasattr(obj,name). 判断object中有没有一个name字符串对应的方法或属性
getattr(obj,name,default=None)
setattr(x,y,v). 等价于 x.y= v
delattr(x,y)。等价于 del x.y
1 class Student: 2 def __init__(self,name,age,sex): 3 self.name = name 4 self.age = age 5 self.sex = sex 6 def show_info(self): 7 print("%s的年龄为%s"%(self.name,self.age)) 8 s1 = Student("Ezhizen",18,"boy") 9 print(hasattr(s1,"name")) #判断是否存在name这个属性 10 print(getattr(s1,"name")) #获得name属性值 11 print(getattr(s1,"q","error")) 12 setattr(s1,"hobby","tennis") #设置属性 13 print(s1.__dict__) 14 delattr(s1,"hobby") #删除属性 15 print(s1.__dict__)
__setattr__ __getattr__\__delattr__
1 class Foo: 2 x=1 3 def __init__(self,y): 4 self.y = y 5 def __getattr__(self, item): 6 print("你找的属性不存在") 7 def __setattr__(self, key, value): 8 # self.key = value #进入无限递归 9 print("执行setattr方法") 10 self.__dict__[key] = value 11 def __delattr__(self, item): 12 print("执行delattr方法") 13 # del self.item #进入无限递归 14 self.__dict__.pop(item) 15 f = Foo(10) #执行init函数 执行setattr 16 print(f.x) #属性存在时获得该属性值 17 f.q #属性不存在,执行getattr方法 18 del f.y #执行delattr方法
1 class Foo: 2 x=1 3 def __init__(self,y): 4 self.y = y 5 def __getattribute__(self, item): 6 print('1111') 7 raise AttributeError("不存在") 8 def __getattr__(self, item): 9 print("你找的属性不存在") 10 11 def __setattr__(self, key, value): 12 # self.key = value #进入无限递归 13 print("执行setattr方法") 14 self.__dict__[key] = value 15 def __delattr__(self, item): 16 print("执行delattr方法") 17 # del self.item #进入无限递归 18 self.__dict__.pop(item) 19 f = Foo(10) #执行init函数 执行setattr 20 # print(f.x) #属性存在时获得该属性值 21 f.q #属性不存在,执行getattr方法 22 #如果getattribute也存在,先执行getattribute 抛出attributeerror,执行getattr 23 # del f.y #执行delattr方法