首页 > 代码库 > Python interview - override & overload
Python interview - override & overload
我们先说overload 重载。
在Java中,支持重载,重载的意思是能够定义有相同方法名的方法,传入方法中的参数个数,或者参数类型不同。比如:
int mymethod(int a, int b) int mymethod(int num)
float mymethod(int a, float b) float mymethod(float var1, int var2)
int mymethod(int a, int b) int mymethod(float var1, float var2)
如下的例子是错误的,因为传入的参数个数相同,类型相同,仅仅给了一个不同的命名并不改变具体的方法。
int mymethod(int a, int b, float c) int mymethod(int var1, int var2, float var3)
那么对于python,我们也可以写出这样的方法,举例来说明为什么python不支持overload
def sum(a,b): return a+b def sum(a,b,c): return a+b+c
上述的方法,如果python支持overload,我们运行两个不同的sum方法的时候,会得到不同的结果
print sum(1,2) print sum(1,2,3) # result TypeError: sum() takes exactly 3 arguments (2 given)
当我们想调用第一个sum方法的时候报错。这是因为python不支持overload,第二个同名的方法会覆盖overwrite第一个方法。
所以,当我们想在python中运用类似overload的技巧的时候,更多的我们会使用
default argument values
def ask_ok(prompt, retries=4, complaint='Yes or no, please!')你可以调用这个方法,传入不同个数的参数
ask_ok('Do you really want to quit?') ask_ok('OK to overwrite the file?', 2) ask_ok('OK to overwrite the file?', 2, 'Come on, only yes or no!')
keyword arguments
def parrot(voltage, state='a stiff', action='voom', type='Norwegian Blue'):如果使用的keyword赋值,那么不需要按照顺序传入参数
parrot(1000) # 1 positional argument parrot(voltage=1000) # 1 keyword argument parrot(voltage=1000000, action='VOOOOOM') # 2 keyword arguments parrot(action='VOOOOOM', voltage=1000000) # 2 keyword arguments parrot('a million', 'bereft of life', 'jump') # 3 positional arguments parrot('a thousand', state='pushing up the daisies') # 1 positional, 1 keyword
arbitrary argument lists
def write_multiple_items(file, separator, *args): file.write(separator.join(args))
####################################################################################################################################
我们接着说python的override重写
在Java中,我们用extends 父类方法来继承,继承父类的方法,并可以重写方法中的内容。同时可以用super关键词调用父类的方法。
Python中可以做同样的事,没有extends,有super。
class Parent(object): def myMethod(self): print 'Calling parent method' class Child(Parent): def myMethod(self): print 'Calling child method' p = Parent() p.myMethod() c = Child() c.myMethod() # result Calling parent method Calling child method
Child继承了Parent类,重写了myMethod方法。当然也可以不继承myMethod方法,随便自己写自己的方法。
但是继承了之后,可以使用super关键词来调用父类的方法
class Parent(object): def myMethod(self): print 'Calling parent method' class Child(Parent): def childMethod(self): print 'Calling child method' super(Child, self).myMethod() p = Parent() p.myMethod() c = Child() c.childMethod() # result Calling parent method Calling child method Calling parent method
同样的代码,加入了super关键词,就等于在调用childMethod方法的时候,会再调用父类的myMethod方法。
####################################################################################################################################
扩展
1:在继承中基类的构造(__init__()方法)不会被自动调用,它需要在其派生类的构造中亲自专门调用。有别于C#
2:在调用基类的方法时,需要加上基类的类名前缀,且需要带上self参数变量。区别于在类中调用普通函数时并不需要带上self参数
3:Python总是首先查找对应类型的方法,如果它不能在派生类中找到对应的方法,它才开始到基类中逐个查找。(先在本类中查找调用的方法,找不到才去基类中找)。
class BaseClass: def __init__(self, name, age): self.name = name self.age = age print "baseclass is inited" def speak(self, name): print "base class is speaking: %s" % nameclass SubClass(BaseClass): def __init__(self, name, age, salary): BaseClass.__init__(self, name, age)# 调用父类函数要记得带上self,区别普通调用不需要self self.salary=salary print "SubClass is inited and the salary is: %s" % self.salary def talk(self, sth): print "%s talking: %s" % (self.name, sth) BaseClass.speak(self, sth) <span style="font-family: Arial, Helvetica, sans-serif;"># 调用父类函数要记得带上self,区别普通调用不需要self</span>if(__name__=="__main__"): s=SubClass("Joan",1,800) s.talk("a story")# resultbaseclass is initedSubClass is inited and the salary is: 800Joan talking: a storybase class is speaking: a story
假如子类中不用__init__初始化函数,那么子类会继承父类的属性
class BaseClass: def __init__(self, name, age): self.name = name self.age = age print "baseclass is inited" def speak(self, name): print "base class is speaking: %s" % name class SubClass(BaseClass): #def __init__(self, name, age, salary): # BaseClass.__init__(self, name, age) # self.salary=salary # print "SubClass is inited and the salary is: %s" % self.salary def talk(self, sth): print "%s talking: %s, his age is %d" % (self.name, sth, self.age) BaseClass.speak(self, sth) if(__name__=="__main__"): s=SubClass("Joan",1)# 初始化的时候,会先在本类中调用init方法,没有就调用父类的 s.talk("a story") s.speak("directly use baseclass function") # 通过子类调用speak方法,会先在子类中查找,找到就直接调用,找不到就会寻找父类中调用 # result baseclass is inited Joan talking: a story, his age is 1 base class is speaking: a story base class is speaking: directly use baseclass function
当我们注释了子类的__init__方法之后,就会继承父类的属性。
多重继承
class P1 #(object): def foo(self): print 'p1-foo' class P2 #(object): def foo(self): print 'p2-foo' def bar(self): print 'p2-bar' class C1 (P1,P2): pass class C2 (P1,P2): def bar(self): print 'C2-bar' class D(C1,C2): pass
注意到上述代码中,我们注释了class继承object,这类属于经典类,我们来调用函数
d = D() d.foo() d.bar() # result p1-foo p2-bar
当我们把object的注释取消掉之后,运行同样的代码
class P1 (object): def foo(self): print 'p1-foo'class P2 (object): def foo(self): print 'p2-foo' def bar(self): print 'p2-bar'class C1 (P1,P2): passclass C2 (P1,P2): def bar(self): print 'C2-bar'class D(C1,C2): passd = D()d.foo()d.bar()print "MRO:", [x.__name__ for x in D.__mro__]# resultp1-fooC2-barMRO: ['D', 'C1', 'C2', 'P1', 'P2', 'object']
如上所述,我们得到不同的结果。
我们可以使用__mro__属性来查看查找顺序。
参考:
http://beginnersbook.com/2013/05/method-overloading/
http://forums.udacity.com/questions/20750/method-overloading-in-python
https://docs.python.org/2/tutorial/controlflow.html#more-on-defining-functions
http://2577885.blog.51cto.com/2567885/669322
http://blog.csdn.net/seizef/article/details/5310107
http://www.cnblogs.com/Joans/archive/2012/11/09/2757368.html
Python interview - override & overload