在Python中定义类时,如何为多个变量赋值?

时间:2013-02-04 19:28:54

标签: python class variables assign

我已经开始学习python的第一步了,我正在尝试开始使用类。

到目前为止,我有这个简化版本:

class ThingsInTheFridge(object):
  def __init__(self):
    self.milk = False
    self.yogurt = False
    self.bread = True
    self.umbrella = True

我班上将会有大约30件事情,每件事都被分配为真或假(我已经缩短了这个问题的清单。)

分配它们的最有效方法是什么?

我已经考虑过这个但是它似乎没有改善,特别是当列表增加时:

self.milk, self.yogurt = False, False

编辑: 我或许应该提到类中有其他项目(我省略了它们因为我认为不重要):

class ThingsInTheFridge(object):
  def __init__(self):
    self.milk = False
    self.yogurt = False
    self.bread = True
    self.umbrella = True
    self.bulb = "maker name"
    self.shoes = 2

4 个答案:

答案 0 :(得分:4)

如果你真的关心运行时效率,你几乎肯定会在错误的地方找工作。如果初始化你的成员需要太长时间(这是非常不可能的......但如果你发现并发现这是热点...),正确的答案是使用__slots__,而不是改变初始化的方式。

如果您关心程序员效率(可读性,以及可写性较小),您可以随时执行此操作:

self.milk = self.yogurt = False

如果你想更动态地做事,你可以用setattr做这样的事情,但我不推荐它:

class ThingsInTheFridge(object):
    false_things = ('bread', 'umbrella')
    true_things = ('milk', 'yogurt')
    def __init__(self):
        for thing in ThingsInTheFridge.false_things:
            setattr(self, thing, False)
        for thing in ThingsInTheFridge.true_things:
            setattr(self, thing, True)

我不推荐它的原因是,如果你需要在这个级别动态地做事,你也可能需要在 access 级别动态,这意味着你真的应该是使用dictset,如Lattyware所述。

你也可以在类式系统之上过度自我构建原型风格的OO系统,或创建一个基于类信息等初始化实例的元类,但是,这句话的开头表示那将会过火。

答案 1 :(得分:4)

我认为这会显示存储数据模型的问题。您可能希望使用类似集合的数据结构,而不仅仅是属性。

例如:

items = {"milk", "yogurt", "bread", "umbrella"}
stored = set()

然后只需将您想要的内容存储在stored集中。集合具有非常快的成员资格检查性能,因此要检查,您可以简单地执行"milk" in stored

如果你真的想保留你拥有的界面,你可以使用__getattr__()覆盖你在要求属性时获得的动作:

def ___getattr__(self, item):
    return item in self.stored

这会将False返回到不在冰箱内的任何物品,如果您需要它只能回复可能的物品,这很容易就可以完成:

def ___getattr__(self, item):
    if item not in self.items:
        raise AttributeError
    return item in self.stored

当然,也可以进行设置:

def __setattr__(self, item, value):
    if item in self.items:
        if value:
            self.stored.add(item)
        else:
            self.stored.remove(item)
    else:
        ...

另一种选择是对True / False的谴责 - 我不能说我认为要么特别好,要么更适合你的项目。只要使用最适合你的东西。

答案 2 :(得分:1)

我认为您的主要关注点应该是可读性和基础数据结构。

像这样的东西是非常易读的(并且可能),因为你可以通过滚动自己来实现高性能:

from collections import Counter

class Fridge(object):
    def __init__(self,things,name):
        self.things=Counter(things)
        self.wanted=set()
        self.name=name

    def look(self, thing):
        print 'There are {} {} in {}'.format(self.things[thing],thing,self.name)

    def stare_inside(self):
        cathave=sorted([(co,it) for it,co in self.things.items() if co])
        print '{} items in {}:'.format(len(cathave),self.name)
        for i, item in enumerate(cathave,1):
            print '   {}: {} -- {}'.format(i,item[1],item[0])

    def shop(self):
        shop_list=[it for it,co in self.things.items() if co==0]
        for item in shop_list:
            del self.things[item]
        shop_list.extend(list(self.wanted))
        self.wanted=set()
        print "shopping list:"
        for i, item in enumerate(sorted(shop_list),1):
            print '   {}: {}'.format(i,item)    

    def consume(self,thing,count):
        if self.things[thing]>=count:
            self.things[thing]-=count   
        else: 
            print 'Not enough {} to consume {} -- {} in the {}.'.format(
                  thing,count,self.things[thing],self.name)
            self.wanted.add(thing)

    def stock(self,things):
        self.things+=Counter(things)

现在尝试一下:

>>> kitchen=Fridge({'coke':2, 'whole milk':1,'ketchup':1, 'anchovies':24},'kitchen fridge')
>>> kitchen.look('coke')
There are 2 coke in kitchen fridge
>>> kitchen.stock({'coke':1,'pepsi':2,'banana':3})
>>> kitchen.stare_inside()
6 items in kitchen fridge:
   1: ketchup -- 1
   2: whole milk -- 1
   3: pepsi -- 2
   4: banana -- 3
   5: coke -- 3
   6: anchovies -- 24
>>> kitchen.consume('red bull',22)
Not enough red bull to consume 22 -- 0 in the kitchen fridge.
>>> kitchen.consume('coke',3)
>>> kitchen.consume('whole milk',1)
>>> kitchen.stare_inside()
4 items in kitchen fridge:
   1: ketchup -- 1
   2: pepsi -- 2
   3: banana -- 3
   4: anchovies -- 24
>>> kitchen.shop()
shopping list:
   1: coke
   2: red bull
   3: whole milk

这是基于collection module Counter class.你不太可能想出一些更快的原生Python。

答案 3 :(得分:0)

使用一组字符串而不是单个标志成员实际上可能会更好。像下面这样的东西可能更适合你似乎想要做的事情。

class ThingsInTheFridge:
    """I represent a collection of items in a refrigerator.

    I contain a few things by default.  You can add and remove items as
    well as test for membership.

    >>> things = ThingsInTheFridge()
    >>> object() in things
    False
    >>> things.store_item('foo')
    >>> 'foo' in things
    True
    """
    def __init__(self):
        self._items = set()
        self.store_item('bread')
        self.store_item('umbrella')
    def store_item(self, item):
        """Add an item to the fridge.
        :param item: the item to add.

        Items are coerced into strings and normalized before they are
        added to the internal list.

        >>> things = ThingsInTheFridge()
        >>> things.store_item(False)
        >>> 'false' in things
        True
        >>> 'FALSE' in things
        True
        >>> False in things
        True
        """
        self._items.add(str(item).lower())
    def __contains__(self, item):
        """Check if an item is in the fridge.
        :param item: item to check for.

        Items are coerced into strings and normalized to match the processing
        in :py:meth:`store_item`.

        >>> things = ThingsInTheFridge()
        >>> things.store_item('Milk')
        >>> 'Milk' in things, 'milk' in things, 'MiLk' in things
        (True, True, True)
        """
        return str(item).lower() in self._items