2012-11-20 48 views
2

我有一些類:蟒蛇採用不同的方式調用類的方法

class RSA: 
CONST_MOD=2 
def __init__(self): 
    print "created" 

def fast_powering(self,number,power,mod): 
    print "powering" 

我想實例並調用方法fast_powering:

def main(): 
    obj=RSA() # here instant of class is created 
    val=obj.fast_powering(10,2,obj.CONST_MOD) # and we call method of object 
    print val 

,它工作正常!

但是我發現,我可以做一點點不同的方式太像:

def main(): 
obj=RSA #do we create a link to the class without creating of object , or what? 
val=obj().fast_powering(10,2,obj().CONST_MOD) # and here we do something like 
      # calling of static method of class in C++ without class instantiation, 
      # or ? 
print val 

對不起,我覺得有點在C++的方式,但無論如何 我非常驚訝地它也能工作!
這裏究竟發生了什麼?哪種方式更受歡迎?這對我來說有些神祕。

在此先感謝您的回覆!

回答

3

在你的榜樣,你正在做的:

obj = RSA 

這是剛剛裝訂obj到任何被綁定到RSA,這是你的實例類RSA名稱。然後,你做:

obj().fast_powering(…) 

即相當於創造RSA一個實例,並調用該方法fast_powering就可以了。請注意,通過這種方式,每次調用都會得到一個新的RSA實例,這可能不是您想要的。您還會注意到,上面引用的行中調用了__init__方法。還認爲:

>>> class RSA: 
... def __init__(self): 
...  print("foo") 
... 
>>> obj = RSA 
>>> obj() is obj() 
foo 
foo 
False 

在這裏,我們看到實際上聲明obj() is obj()創建了兩個對象,這當然是不相同的。這是不是你的第一個例子,如使用證明:

>>> class RSA: 
... def __init__(self): 
...  print("foo") 
... 
>>> obj = RSA() 
foo 
>>> obj is obj 
True 
+0

+1對於省略號使用正確的字形。開玩笑,答案很好,但我希望看到更多。 – delnan

1

obj = RSA後,雙方RSAobj指的是同一類 - 你但是創造的RSA一個實例。試想一下:

class Foo: 
    def __init__(self): 
     print 'Foo' 

Bar = Foo 

Foo() 
Bar() 

輸出:

 
Foo 
Foo 

無論在哪個方式更可取:這真的取決於你正在嘗試做的。但總的來說,第一種方法更可取,除非您有充分理由使用第二種方法。

+0

那麼,如果這個鏈接被創建Bar = Foo,是否創建了類的實例? – Tebe

+2

@gekannt否,'Bar'只是被定義爲'Foo'類。注意當我們做'Bar = Foo'時,'init'沒有被調用。 – arshajii

1

嗯......事實證明,class RSA是一個實例太多,所以你可以將其存儲在變量(這是你的第二個方法是做),儘管我需要指出你在兩個方面都沒有做同樣的事情。當你這樣做:

val=obj().fast_powering(10,2,obj().CONST_MOD) 

你實際上是調用RSA的構造兩次(你有兩個obj()調用),這樣的話你會看到兩個控制檯上的「創建」的消息。

在Python中做同樣的事情有很多奇怪的方法。爲了可讀性起見,我更喜歡「正規」的方式(在你的第一種方法中所示),但這裏的東西都是合法可行的一個簡單的例子:

#!/usr/bin/env python 

class RSA(object): 
    CONST_MOD=2 
    def __init__(self): 
     print "created" 

    def fast_powering(self,number,power,mod): 
     print "powering" 

def method1_good(): 
    obj=RSA() # here instant of class is created 
    val=obj.fast_powering(10,2,obj.CONST_MOD) # and we call method of object 
    print val 

def method2_bad(): 
    obj=RSA #do we create a link to the class without creating of object , or what? 
    val=obj().fast_powering(10,2,obj().CONST_MOD) 
    print val 

def method3_badToo(): 
    getattr(RSA(), "fast_powering")(10,2,RSA().CONST_MOD) 

def method4_areYouNuts(): 
    for key, val in globals().iteritems(): 
     if isinstance(val, type) and (key == "RSA"): 
      obj = val() 
      getattr(obj, "fast_powering")(10,2,obj.CONST_MOD) 
      break 

if __name__ == "__main__": 
    print "Works with method1?" 
    method1_good() 
    print "Works with method2?" 
    method2_bad() 
    print "Works with method3?" 
    method3_badToo() 
    print "Works with method4?" 
    method4_areYouNuts() 

這也許可以給你一些東西尋找,如: Globals and Locals Gettattr和SETATTR(12

如果你想挖多一點......瘋狂的事情你可以做metaclasses ...(在的一個解釋在StackOverflow中見過的最佳答案)

+0

實際上我並沒有看到第二個''obj()''調用(你的第二段)。 –

+0

我從問題的第三個「代碼塊」(第二個main()示例)中複製它 – BorrajaX

+0

哦,對,我忽略了參數中的obj(),從不介意。 –