【问题标题】:How to access an object in a list by property?如何按属性访问列表中的对象?
【发布时间】:2012-11-22 02:26:52
【问题描述】:

考虑一个对象列表和一个适用于一个对象的方法:

beers = []
beers.append(Beer('Carlsberg', 'tasty'))
beers.append(Beer('Guinness', 'bitter'))
beers.append(Beer('Leffe', 'perfect'))

def howIsBeer (name):
    taste = ???
    print taste

Class Beer:
    def __init__ (self, name, taste):
        self.name = name
        self.taste = taste

如果只提供啤酒名称,howIsBeer() 方法将如何获得啤酒的味道? 我的第一个倾向是迭代beers 列表,但作为Python 我怀疑有更直接的方法。有吗?

【问题讨论】:

  • 有什么理由不能只使用dict 吗?
  • 我正在尝试学习如何处理我将拥有任意唯一对象属性的情况。每个属性也可能有一个电话号码或一个地理坐标字段(每个都是唯一的)。我可能并不总是在“主键”上搜索,尽管我将其限制为在对象中唯一的属性。
  • 然后按照您的说明顺序扫描列表,创建多个支持字典,或者考虑将其存储在 sqlite3 内存数据库中
  • 你拼错了 Carlsberg 和 Leffe :)
  • @NPE:那只是因为我不知道如何拼写 Guinness 并用谷歌搜索。另外两个我很确定!

标签: python oop list object


【解决方案1】:

实在想不出更好的办法,只需使用for-loop。

def howIsBeer(name):
    for beer in beers:
        if beer.name == name:
            return beer.taste

In [1]: howIsBeer("Carlsburg")
Out[1]: tasty

还要注意,关键字class 用小号c 书写。您还必须使用它来创建实例之前定义您的类。

编辑: 正如评论中所建议的,一种方法是定义字典。如果你觉得它有用,你可以使用下面的代码。但是请注意,仅当您拥有 HUGE 数量的 Beer 对象并且性能速度对您非常重要时,才建议这样做。否则使用提供的第一个代码

class Beer:
    names = {}
    def __init__(self, name, taste):
        Beer.names[name] = self
        self.name = name
        self.taste = taste

In [3]: Beer.names["Carlsburg"].taste
Out[3]: tasty

【讨论】:

  • 你不需要使用多个字典 - 比如说 - 你有一个名称是 Beer.name 并且属性存储为字典的字典。请参阅下面的my answer
  • 您在这种情况下使用字典的方式是最糟糕的方式,请参阅上面的my answer
  • 谢谢,我会使用循环。第二个代码示例只有在我事先知道需要搜索哪个属性时才有用,当然也只有当 Beer 类是我自己的代码时。
  • @Mahi 虽然这个答案具有误导性,但您这样做的方式是,每个 Beer 类都会创建自己的字典,其中只有一个 Beer 对象,并且存储了 Beer.name 变量两次。
  • @dotancohen 您可以为每个值创建一个字典 - 但正如我所提到的,这仅推荐用于 HUGE 列表,例如 10000 个对象等。通过快速继承,您可以将它用于任何类 :) 但如果第一个适合您,请不要使用它。
【解决方案2】:

只需遍历列表并检查每一个。

您需要稍微移动一下代码,因为class def 需要高于该类的使用,并且它还使用一个小的c。您还应该注意它不被识别的情况。

你也拼错了嘉士伯:/

class Beer:
    def __init__ (self, name, taste):
        self.name = name
        self.taste = taste



beers = []
beers.append(Beer('Carlsberg', 'tasty'))
beers.append(Beer('Guinness', 'bitter'))
beers.append(Beer('Lef', 'perfect'))


def howIsBeer (name):

    taste = "I have no idea"

    for beer in beers:
        if beer.name == name:
            taste = beer.taste

    print taste



howIsBeer("Carlsberg") # tasty

不过我会这样做(使用此处的字典可以灵活地拥有多个属性):

beers = {}
beers["Lef"] = {"taste": "tasty"}
beers["Staropramen"] = {"taste": "tasty"}
beers["Peroni"] = {"taste": "tasty"}
beers["Coors Light"] = {"taste": "What is this?!"}


def howIsBeer (name):

    taste = "I have no idea"

    if name in beers:
        taste = beers[name]["taste"]

    print taste



howIsBeer("Lef")

如果你只是想存储口味,那么你可以这样做:

beers = {}
beers["Lef"] = "tasty"
beers["Staropramen"] = "tasty"
beers["Peroni"] = "tasty"
beers["Coors Light"] = "What is this?!"


def howIsBeer (name):

    taste = "I have no idea"

    if name in beers:
        taste = beers[name]

    print taste



howIsBeer("Lef")

如果您要存储一系列对象 - 正如您在问题中提到的那样 - 那么您需要一个对象字典 - 而不是作为类变量的字典。

beers = {}

def add_beer(beer):
    beers[beer.name] = beer

然后获取您正在查看的啤酒的数据;

if beer in beers:
    beers[beer].taste

这可以扩展到任何对象类型,我相信这正是您正在寻找的;

例如

cheeses = {}
add_cheese(cheese):
    cheeses[cheese.name] = cheese

在哪里

class cheese:
    def __init__(self, name, smelliness, hardness, colour, country):
        self.name = name
        self.smelliness = smelliness
        self.hardness = hardness
        self.colour = colour
        self.country = country

【讨论】:

  • 这 a) 使用字典 b) 与我的答案有何不同?
  • @Mahi 我正在编辑我的帖子 - 刚刚发布了评论 - 抱歉!
  • @Mahi 第一位不是不,你到达那里的速度更快,我只是在name 不在beers 中时添加了一些说明 - 在这种情况下你的howIsBeer永远不会回来
  • 如果啤酒中没有名字,我的howIsBeer会返回None,表示找不到啤酒。
  • @Mahi 对不起,我不同意你的观点。当您只想存储少量属性时,为什么还要添加创建类的麻烦。如果它只是一个属性,那么你可以存储它。
【解决方案3】:

为了完整起见,我找到了一种使用Linq-like single-line statement 的方法,它还具有更易于阅读的优点:

taste = [b.taste for b in beers if b.name==name][0]

末尾的[0] 是返回第一项,因为查询返回匹配项的列表。所以要获得整个列表:

[b.taste for b in beers if b.name==name]

这就是我喜欢 Python 的原因!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-13
    • 2014-03-16
    • 2015-08-12
    相关资源
    最近更新 更多