【问题标题】:How do you assign one value to multiple variables when defining a class in Python?在 Python 中定义一个类时,如何为多个变量分配一个值?
【发布时间】:2013-01-19 14:01:03
【问题描述】:

我已经开始迈出学习 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

【问题讨论】:

  • self.mild = self.yogurt = False
  • 我不知道你的问题,或者你为什么以这种方式使用一个类 - 但我可以想到几个替代解决方案:字典 - 你可以迭代设置值,或者一个集合 - 值的存在/不存在是真/假。这些可能会导致更少的代码。
  • 当您问“分配它们的最有效方法是什么?”时,您的真正意思是“高效”,例如“在运行时花费最少的纳秒”,或者诸如“最好地利用我的作为程序员的时间”?
  • 你在冰箱里放了一些很奇怪的东西……

标签: python class variables assign


【解决方案1】:

如果您真的关心运行时效率,那么您几乎肯定是找错地方了。如果初始化您的成员花费的时间太长(这不太可能……但如果您分析并发现这是热点……),正确的答案是使用__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 系统,或者创建一个基于类信息初始化实例的元类等,但是,正如这句话的开头所表明的那样, 那就太过分了。

【讨论】:

  • 这实际上并不高效。做最容易阅读的事情。
  • @MelNicholson:我只是假设他的意思是“程序员效率”而不是“运行时效率”。但你是对的,我需要说清楚。正在编辑……
【解决方案2】:

我认为这表明您的数据存储模型存在问题。您可能希望使用像集合这样的数据结构,而不仅仅是属性。

例如:

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

然后将您想要的存储在stored 集中。 Sets 在成员检查方面具有非常快的性能,所以要检查,您可以简单地使用"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 的dict - 我不能说我认为任何一个都特别好,一个可能更适合您的项目。只需使用最适合您的方式即可。

【讨论】:

    【解决方案3】:

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

    这样的东西非常易读,并且(很可能)与你自己滚动获得的一样高性能:

    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 的东西。

    【讨论】:

      【解决方案4】:

      实际上,使用一组字符串而不是单个标志成员可能会更好。对于您似乎正在尝试做的事情,以下内容可能会更好。

      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
      

      【讨论】:

        猜你喜欢
        • 2014-02-28
        • 1970-01-01
        • 2016-12-13
        • 1970-01-01
        • 2020-03-01
        • 1970-01-01
        • 2019-06-04
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多