一、python之静态
1.1静态属性
我们知道类既有函数属性又有数据属性,实例只有数据属性,我们在使用实例调用类的函数属性并运行时,总要带上函数后面的括号才能运行,不然总是调用函数的内存地址。
问题:那么我们如何能像调用数据属性一样调用函数属性呢?
类中提供了@property关键字,可以看成@property是一个装饰器,装饰器的作用是调用类的函数属性key值时,直接来运行该key值对应的函数。像是调用类的属性一样来直接调用并运行类的函数,具体操作如:
1 class Room: 2 def __init__(self,name,owner,width,length,heigth): 3 self.Name=name 4 self.Owner=owner 5 self.Width=width 6 self.Length=length 7 self.Heigth=heigth 8 9 @property 10 def cal_area(self): 11 return self.Width*self.Length 12 13 r1=Room('客厅','czd',10,10,3) 14 r2=Room('客厅','lzq',9,9.5,4) 15 16 print(r1.cal_area) 17 print(r2.cal_area) 18 19 print(r1.Name) 20 print(r2.Name)
注意,当类中的函数有其他参数时(非self),加上@property关键字会报错,提示缺少必要的位置参数,猜想应该是装饰的问题,可能需要自定义装饰器才行。可以判断,@property的作用是:直接运行被装饰的函数,不能带参数,表面上看就是在被装饰的函数后面直接加括号。如:
import time class Door(): "门的类" address = "浙江省杭州市" def __init__(self,size,color,type):#构造函数 "初始化门的数据" self.size = size self.color = color self.type = type @property def open(self): "门打开的方法" print("这个%s门打开了" %self.type) @property def off(self,time): "门关闭的方法" print("这个%s门关闭了,时间为;%s" %(self.type,time)) door1 = Door(16, 'red', '木门') #调用数据属性 print(door1.size) print(door1.address) #调用函数属性 # door1.open() #函数后面的括号每次都必须要带上 #实例调用类的静态属性 print(Door.__dict__) door1.open time1 = time.strftime('%Y-%m-%d %H:%M:%S',time.localtime()) # door1.off(time1) #传参无效,应该要自定义对应的装饰器才行
1.2类方法
类方法是将类本身作为对象进行操作的方法。他和静态方法的区别在于:不管这个方式是从实例调用还是从类调用,它都用第一个参数把类传递过来。但是注意到self有特殊含义,它是指实例的本身,也就是说要使用self必须要先实例化才行。为了解决这个问题,我们引入另一个@classmethod装饰器后,就可以直接通过类来调用类的函数属性了(该函数带类的数据属性参数),如:
class Room: tag = 1 def __init__(self, name, owner, width, length, heigth): self.Name = name self.Owner = owner self.Width = width self.Length = length self.Heigth = heigth def cal_area(self): return self.Width * self.Length @classmethod def tell_info(cls,x): print(cls) print('--->>',cls.tag,x) Room.tell_info(10)
1.3静态方法
静态方法是类中的函数,不需要实例。静态方法主要是用来存放逻辑性的代码,主要是一些逻辑属于类,但是和类本身没有交互,即在静态方法中,不会涉及到类中的方法和属性的操作。可以理解为将静态方法存在此类的名称空间中。事实上,在python引入静态方法之前,通常是在全局名称空间中创建函数。
例如:
class Room: tag = 1 def __init__(self, name, owner, width, length, heigth): self.Name = name self.Owner = owner self.Width = width self.Length = length self.Heigth = heigth def cal_area(self): return self.Width * self.Length @staticmethod def bathroom(a,b,c): print('%s %s %s正在洗澡' %(a,b,c)) Room.bathroom('老赵','老李','老孔') r1=Room('客厅','czd',10,10,3) r1.bathroom('老赵','老李','老孔')
二、python之组合
2.1组合
组合就是一个类中使用到另一个类,从而把几个类拼到一起。组合的功能也是为了减少重复代码。
class School: def __init__(self,name,addr): self.name=name self.addr=addr def zhao_sheng(self): print('%s正在招生'%self.name) class Course: def __init__(self,name,price,period,school): self.name=name self.price=price self.period=period self.school=school s1=School('福州大学','旗山校区') s2=School('福州大学','晋江校区') s3=School('福州大学','厦门校区') c1=Course('物流',8000,'1year',s1) msg=''' 1 福州大学 旗山校区 2 福州大学 晋江校区 3 福州大学 厦门校区 ''' while True: print(msg) menu={ '1':s1, '2':s2, '3':s3 } choice=input('选择学校>>:') school_obj=menu[choice] name=input('课程名>>:') price=input('课程费用》:') period=input('课程周期>>:') new_course=Course(name,price,period,school_obj) print('课程%s属于%s学校' %(new_course.name,new_course.school.name))
三、继承
3.1继承
面向对象的编程带来的主要好处之一是代码的重用,实现这种重用的方法之一是通过继承机制。继承完全可以理解成类之间的类型和子类型关系。
3.2何时使用继承
假如我需要定义几个类,而类与类之间有一些公共的属性和方法,这时我就可以把相同的属性和方法作为基类的成员,而特殊的方法及属性则在本类中定义,这样只需要继承基类这个动作,就可以访问到基类的属性和方法了,它提高了代码的可扩展性。
3.3继承的特点
1:在继承中基类的构造(__init__()方法)不会被自动调用,它需要在其派生类的构造中亲自专门调用。有别于C#
2:在调用基类的方法时,需要加上基类的类名前缀,且需要带上self参数变量。区别于在类中调用普通函数时并不需要带上self参数
3:Python总是首先查找对应类型的方法,如果它不能在派生类中找到对应的方法,它才开始到基类中逐个查找。(先在本类中查找调用的方法,找不到才去基类中找)。
3.4继承的顺序
class A: def test(self): print(A) class B(A): def test(self): print(B) class C(A): def test(self): print(C) class D(B): def test(self): print(D) class E(C): def test(self): print(E) class F(D,E): def test(self): print(F) f1=F() f1.test() #新式类顺序 F-->D-->B-->E-->C-->A print(F.__mro__)
3.5接口继承
接口继承就是(基类)父类定义好2个函数属性(接口),所有的子类必须有这2个函数属性,缺一不可,不是说省代码的,是用来做强制性约束的接口继承。
基类里面的方法不用具体的实现,只是一个规范而已。例如:
import abc class All_file(metaclass=abc.ABCMeta): @abc.abstractmethod def read(self): pass @abc.abstractmethod def write(self): pass class Disk(All_file): def read(self): print('disk read') def write(self): print('disk write') class Cdrom(All_file): def read(self): print('Cdrom read') def write(self): print('Cdrom write') class Mem(All_file): def read(self): print('Mem read') def write(self): print('Mem write') m1=Mem() m1.read() m1.write()
四、补充
4.1子类中调用父类
class Vehicle: Country='China' def __init__(self,name,speed,load,power): self.name=name self.speed=speed self.load=load self.power=power def run(self): print('开动啦') print('开动啦') print('开动啦') print('开动啦') print('开动啦') class Subway(Vehicle): def __init__(self,name,speed,load,power,line): Vehicle.__init__(self,name,speed,load,power) self.line=line def show_info(self): print(self.name,self.speed,self.load,self.power,self.line) def run(self): Vehicle.run(self) print("%s %s 线,开动啦" %(self.name,self.line)) line1=Subway('兰州地铁','100m/s',1000,'电',1) line1.show_info() line1.run()
利用Super方法调用:
#Super方法 class Vehicle: Country='China' def __init__(self,name,speed,load,power): self.name=name self.speed=speed self.load=load self.power=power def run(self): print('开动啦') print('开动啦') print('开动啦') print('开动啦') print('开动啦') class Subway(Vehicle): def __init__(self,name,speed,load,power,line): super().__init__(name,speed,load,power) self.line=line def show_info(self): print(self.name,self.speed,self.load,self.power,self.line) def run(self): super().run() print("%s %s 线,开动啦" %(self.name,self.line)) line1=Subway('兰州地铁','100m/s',1000,'电',1) line1.show_info() line1.run()