2012-04-05 33 views
1

我想知道是否可以寫count(vanilla)而不是vanilla.count()?它類似於len(list),但我想做len(myclass)。是否有可能在我的用戶定義類上這樣實現?下面是我寫的一個虛擬課堂來問這個問題。謝謝。我可以切換此功能vanilla.count()

class IceCream(): 
    # Flavor is a string 
    # Toppings is a list of strings 
    def __init__(self, flavor, toppings,): 
     self.name = flavor 
     self.toppings = toppings 
    # Return the number of toppings 
    def count(self): 
     return len(self.toppings) 
    def __str__(self): 
     return "{0} flavor ice cream".format(self.name) 


vanillaToppings = ['chocolate chips', 'fudge', 'penuts'] 
vanilla = IceCream('Vanilla', vanillaToppings) 
print(vanilla, 'with', vanilla.count(), 'kind of toppings!') 
# Is it possible? If so, how do I do it? 
# print(vanilla, 'with', len(vanilla), 'kind of toppings!') 

回答

2

如何利用Python的special methods之一:__len__

調用以實現內置函數len()。應該返回對象的長度,整數> = 0

class IceCream(): 
    # Flavor is a string 
    # Toppings is a list of strings 
    def __init__(self, flavor, toppings): 
     self.name = flavor 
     self.toppings = toppings 

    # Return the number of toppings 
    def __len__(self): 
     return len(self.toppings) 

    def __str__(self): 
     return "{0} flavor ice cream".format(self.name) 


vanillaToppings = ['chocolate chips', 'fudge', 'penuts'] 
vanilla = IceCream('Vanilla', vanillaToppings) 
print(vanilla, 'with', len(vanilla), 'kind of toppings!') 

我猜的計數長度意思是在這種情況下有些可以互換的,那麼爲什麼不使用熟悉的東西?

+0

是的,我注意到'__len__'的作品,但是如果我想做'__count__'呢?在那種情況下,無論如何,我可以把它放在我的課堂上,而不是在課堂外單獨分開? – George 2012-04-05 05:25:15

+1

號'count()'不是像'len()'這樣的內置函數。 – Amber 2012-04-05 05:25:43

+0

但是我們可以重載所有的內置函數嗎? (通過重載,我想我應該說:我們可以將它們定義爲我們認爲合適的?) – George 2012-04-05 05:29:48

2

len()是一個函數,它獲取所傳遞的任何長度。所以你可以寫一個函數count()傳遞一個對象,並對它進行計數(然而你定義了「計數」)。

len()函數調用實例上的特殊方法__len__()。你可以爲count()定義一個類似的界面,以便那些想要使用你的函數的人可以在他們自己的類上定義一個特殊的方法供count()使用。 (不要用兩個前導和兩個尾隨下劃線來命名;這是保留給Python的,一個前導和尾隨下劃線是我的建議。)然後你只需在你自己的對象上實現這個接口。

因此,像這樣:

def count(obj): 
    return obj._count_() 

class IceCream(object): 
    def _count_(self): 
     return len(self.toppings) 

三苦建議只是在你的類實現__len__(),並使用len()。這也是一個很好的解決方案,但它可能會產生其他容器或迭代器方法可用的印象。

+0

你的建議是我寫了一個'def count(IceCream):'外面的方法?我是否正確閱讀?對不起,我對你答案的第二部分有點困惑。 「定義一個類似的協議」...? – George 2012-04-05 05:28:03

+0

@kindall:*但它可能會產生其他容器或迭代器方法可用的印象* - 有趣的是,我沒有想到這一點;但迭代冰淇淋澆頭可能不是完全沒有意義:) – miku 2012-04-05 05:31:00

+0

在'IceCream'類中實現'_count_'的方式是,'count(vanilla)'將調用第一個,而'vanilla .count()'調用第二個? – George 2012-04-05 05:33:54

1

請參閱http://docs.python.org/reference/datamodel.html您可以使用哪些魔術方法。你想要的是def __len__(self): return len(self.toppings)

然後你可以使用len(yourinstance)來獲得該函數的返回值。

不能雖然這樣做爲count(yourinstance);至少不是以乾淨的方式。


非清潔的方法是這樣的:

def count(instance): 
    return instance.count() 

我不使用__count__作爲__*__被認爲是官方的Python的東西,如__len__保留。但是,無論如何,請在水平線的下面幾行忘記一切 - 你真的不想這樣做。使用__len__

+0

是的,我可以看到非乾淨的方式,(每次人必須使用我的課程),他們將不得不「複製」一堆代碼,聽起來不是一個好主意...... – George 2012-04-05 05:42:55

+0

實際上'__ * __'僅用於表示不應直接訪問的某些方法/變量。 Python沒有受保護的方法/變量,但下劃線旨在表示應該「保護」的內容。 – 2012-04-05 06:40:39

+2

@JoelCornett:'__something'的確如此,但'__something__'具有不同的含義:*'__double_leading_and_trailing_underscore__':生活在用戶控制的命名空間中的「魔術」對象或屬性。例如。 '__init__','__import__'或'__file__'。不要發明這樣的名字; *([PEP-008](http://www.python.org/dev/peps/pep-0008/))這些字段不會發生名稱混亂:http://codepad.org/ almhNmMB – ThiefMaster 2012-04-05 06:49:09