Python interview - override & overload

7901 ワード

まず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をサポートしている場合、2つの異なるsumメソッドを実行すると、異なる結果が得られます.
print sum(1,2)
print sum(1,2,3)

# result

TypeError: sum() takes exactly 3 arguments (2 given)

最初のsumメソッドを呼び出したいときにエラーを報告します.これはpythonがoverloadをサポートしていないため、2番目の同名のメソッドが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" % name


class 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) #            self,         self

if(__name__=="__main__"):
    s=SubClass("Joan",1,800)
    s.talk("a story")


# result


baseclass is inited
SubClass is inited and the salary is: 800
Joan talking: a story
base 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

インスタンスdがfoo()を呼び出すと、探索順序はD=>C 1=>P 1である
インスタンスdがbar()を呼び出すと、探索順序はD=>C 1=>P 1=>P 2である
すなわち、古典的なクラスの検索方法は、「左から右へ、深さを優先する」方法で属性を検索します.d自己にfooメソッドがあるかどうかを検索し、ない場合は最近の親C 1にメソッドがあるかどうかを検索し、ない場合はP 1でメソッドが見つかるまで上を検索し、検索が終了する.
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):
   pass


class C2 (P1,P2):
   def bar(self):
       print 'C2-bar'


class D(C1,C2):
   pass

d = D()
d.foo()
d.bar()
print "MRO:", [x.__name__ for x in D.__mro__]

# result

p1-foo
C2-bar
MRO: ['D', 'C1', 'C2', 'P1', 'P2', 'object']

上述したように,我々は異なる結果を得た.
インスタンスdがfoo()を呼び出すと、探索順序はD=>C 1=>C 2=>P 1である
インスタンスdがbar()を呼び出すと、探索順序はD=>C 1=>C 2である
新しいクラスの検索方式は,属性を「広さ優先」で検索することであることがわかる.
私たちは__を使うことができます.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