【问题标题】:Python object oriented modelPython 面向对象模型
【发布时间】:2010-07-24 00:42:33
【问题描述】:

我有类似的东西。

一个人拥有属于某个州的同一型号的多种颜色的汽车。

我设计了一个 person 类,它具有 person namecar modelcar yearcar statecar color 作为属性。颜色应该是一个列表,因为一个人可以拥有许多不同颜色但型号相同的汽车。

现在我如何找到并打印两个不同的人,他们拥有相同的汽车型号和相同的汽车颜色,但在面向对象的术语中属于不同的状态?

我是 Python 新手。

在向 person 对象插入颜色时,如何将颜色插入到列表中以及如何从列表中检索?我知道如何为属性执行此操作,但我对列表操作有点困惑。

数据可以是这样的:

person1 ford   [red,blue,yellow] new-york
person2 honda  [red,blue]        new-york
person3 ford   [red,grey]        california
person4 ford   [red]             california
person5 honda  [red]             new-york

现在我的结果应该是:

[(person1,person5)]    (same model car,same color, different state)

【问题讨论】:

    标签: python oop class-design


    【解决方案1】:

    您想了解一些关于列表操作的知识:

    $ python
    Python 2.6.5 (r265:79063, Apr 16 2010, 13:57:41)
    [GCC 4.4.3] on linux2
    Type "help", "copyright", "credits" or "license" for more information.
    >>> l=[]
    >>> l.append("honda")
    >>> l.append("ford")
    >>> l
    ['honda', 'ford']
    >>> l[0]
    'honda'
    >>> l.pop(0)
    'honda'
    >>> l.pop(0)
    'ford'
    >>> l.pop(0)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    IndexError: pop from empty list
    

    如果你想找到几个具有匹配属性的人,你可以做一些 迭代(这里用一些伪代码表示,因为我认为专注于 该算法比专注于 python 来实现它更有用):

    results = []
    foreach p1 in [list of people]
        foreach p2 in [list of people]
            next if p1 == p2
            next if p1.state == p2.state
            next unless p1.car == p2.car
            foreach c1 in p1.colors
                foreach c2 in p2.colors
                    results.append((p1,p2)) if c1 == c2
    

    此代码比较成对的人。它不会将一个人与 他们自己。它不会比较住在同一州的人,因为你 要求“..但属于不同的州”。所以让我们过滤那些相同的状态 人出来。它只比较拥有相同类型汽车的人。 (如果 人们拥有不同类型的汽车,那么您只需添加两个嵌套的 循环。)然后它会记录具有相同颜色汽车的人。

    这个算法有一个潜在的错误:它会报告[(person1, person2), (person2, person1)]。所以条目是重复的。可以修改 算法只搜索人的上三角或下三角,如果你不这样做 想要这个副本:

    results = []
    for i=0; i<people.last_index-1; i++
        for j=i+1; j<people.last_index ; j++
            p1 = people[i] ; p2 = people[j]
            next if p1.state == p2.state
            next unless p1.car == p2.car
            foreach c1 in p1.colors
                foreach c2 in p2.colors
                    results.append((p1,p2)) if c1 == c2
    

    请注意,我们可以删除 next if p1 == p2 检查,因为我们明确不能 获取i == jj 定义为以i+1 开头。

    【讨论】:

    • 非常感谢...帮助很大。
    【解决方案2】:

    您可能希望将statecarperson 分开建模。然后,每个人都可以拥有一个汽车列表,并且生活在一个州(甚至是一个州列表,具体取决于您的车型)。这些是具有关系。如果您愿意,它还允许您在以后继承 car 并在以后创建 sportsCar

    【讨论】:

      【解决方案3】:

      有很多方法可以做到这一点。如果您有大量数据,那么我建议您继续使用 python 的内置 sqlite 支持处理基于数据库的实现(这实际上并不难)。数据库引擎专为搜索而构建。您需要两张桌子,因为每个人可以有多种颜色。 person 表将具有以下列:id、name、model、state。颜色表将具有:personid、color。 personid 列将包含颜色表中的行对应的 id 号。然后,您可以在颜色表中使用相同的 personid 值(这是列表的数据库版本)中的多行。 sqlAlchemy 是一个帮助使用 python 对象实现数据库的库,您可能会发现它更适合您正在尝试做的事情。 sqlAlchemy ORM Tutorial 将引导您使用带有两个表(用户、地址)的 sqlite 数据库,这两个表与您需要的非常相似。

      现在,如果您只想坚持使用 python 类,您将不得不拥有一个人员实例列表并遍历它们以寻找匹配项。一个方便的颜色匹配简化是将颜色列表转换为集合并进行交集。

      >>> s1 = set(['red','blue','yellow'])
      >>> s2 = set(['red','blue'])
      >>> s1.intersection(s2)
      set(['blue', 'red'])
      

      通过人员实例列表进行迭代的捷径是使用 python 的 itertools 库并使用排列生成器。

      from itertools import permutations
      people = ['p1', 'p2', 'p3']
      for p1, p2 in itertools.permutations(people,2):
          print p1, p2
      
      p1 p2
      p1 p3
      p2 p1
      p2 p3
      p3 p1
      p3 p2
      

      希望这足以帮助您一路走好。重新阅读您的问题,您可能需要更多地阅读有关 Python 编程的内容。但是为了解决你关于列表的问题,这里有一些代码可以帮助你。

      class Person(object):
          def __init__(self, name, model, colors, state):
              self.name = name
              self.model = model
              self.colors = colors
              self.state = state
      
      p1 = Person('p1', 'ford', ['red', 'blue'], 'new-york')
      p2 = Person('p2', 'honda', ['red', 'blue'], 'new-york')
      
      persons = [p1, p2]
        # or
      persons = []
      persons.append(p1)
      persons.append(p2)
      
      p1.color.append('yellow')
        # or
      persons[0].color.append('yellow')
      

      【讨论】:

      • 感谢您的回复。很有帮助。