2012-04-05 60 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