面向对象设计包括继承、多态和封装
1在python中多态意味着接口,不是函数签名调用
在有些OOP编程语言中,把多态诠释为基于函数参数签名(传递参数个数即类型)的重载。由于python中没有类型声明,所以函数签名重载是行不通的,因此,python中的多态是基于对象接口而不是类型。
如下所示,若采用函数签名是不能实现多态的。应为def会直接把对象赋值给类的作用域中的变量,所以方法函数的最后一次定义才会被保留。换言之,就好像先定义X=1,然后再定义X=2一样,最后只有X=2保留。
class C: def meth(self,x): print(x,end=' ') def meth(self,x,y): print(x,y,end=' ') X=C() #X.meth(2)#报错,有一个必要的参数缺失 X.meth(2,3)
2OPP和继承
在python,从程序员角度来看,继承是由属性点号实现,并且由此触发实例、类以及任何父类中变量名的搜索;从类设计来看,继承是一种指明集合成员关系的方式:类定义了一个属性集合,可由更具体的集合(如子类)继承和定制。
class Employee: def __init__(self,name,salary=0): self.name=name self.salary=salary def giveRaise(self,percent): self.salary=self.salary+(self.salary*percent) def work(self): print(self.name,' does stuff') def __repr__(self): return '<Employee: name=%s,salary=%s>' %(self.name,self.salary) class Chef(Employee): def __init__(self,name): Employee.__init__(self,name,50000) def work(self): print(self.name,'makes food') class Server(Employee): def __init__(self,name): Employee.__init__(self,name,40000) def work(self): print(self.name,'interfaces with customer') class PizzaRobot(Chef): def __init__(self,name): Chef.__init__(self,name) def work(self): print(self.name,'makes pizza') if __name__=='__main__': bob=PizzaRobot('bob') print(bob) bob.work() bob.giveRaise(0.2) print(bob) for klass in Employee,Chef,Server,PizzaRobot: obj=klass(klass.__name__) obj.work()
3.方法是对象
在python中方法也是一种对象,一般用法与其他对象基本相同,可以将他们赋值给变量名、传递给函数、存储在数据结构中等等。由于方法可以通过实例或类来访问,因此实际上它们在python中有两种形式:
未绑定(类)方法对象:无self
通过对类进行点号运算从而获取类的函数属性,会传回为绑定方法对象。调用该方法时,必须明确提供实例对象作为第一个参数。
绑定方法对象:self+函数
通过实例对象进行点号运算从而获取类的函数属性,会传回绑定方法对象。python在绑定方法对象中自动把实例和函数打包,所以不需要传递实例调用该方法。
class Spam: def doit(self,message): print(message) obj=Spam() obj.doit('hello1') #通过实例调用 Spam.doit(obj,'hello2') #通过类调用方法
