Python 面向对象模型

2 投票
3 回答
544 浏览
提问于 2025-04-16 01:29

我有一个类似这样的情况。

一个人拥有很多颜色的同款车,这些车都属于某个州。

我设计了一个“人”的类,里面有一些属性,比如 人名车款车年份车所在州车颜色。其中,颜色应该是一个列表,因为一个人可以拥有多辆不同颜色但同款的车。

现在,我想知道怎么找到并打印出两个不同的人,他们的车款和颜色相同,但却来自不同的州,这在面向对象的编程中该怎么做呢?

我刚开始学习Python。

在把颜色放进“人”这个对象时,我该怎么把它放进列表里?又该怎么从列表中取出来?我知道怎么处理单个属性,但对列表操作有点困惑。

数据可能是这样的:

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)

3 个回答

2

有很多方法可以做到这一点。如果你有很多数据,我建议你使用数据库来处理,Python自带的sqlite支持其实并不难。数据库引擎是专门用来搜索的。你需要两个表,因为每个人可以有多种颜色。第一个表是“人”表,里面有这些列:id、名字、模型、状态。第二个表是“颜色”表,里面有:personid和颜色。personid这一列会包含颜色表中对应的人的id号。这样,你可以在颜色表中有多行数据,都是同一个personid(这就相当于数据库里的一个列表)。sqlAlchemy是一个库,可以帮助你用Python对象来实现数据库,这可能更适合你想做的事情。sqlAlchemy ORM教程会带你了解如何使用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')
2

你可能想把state(州)和car(车)单独建模,与person(人)分开。这样,每个人可以拥有一辆车的列表,并且可以居住在一个州(或者根据你的模型,甚至可以有多个州)。这些都是拥有关系。这样做还可以让你以后再细分car,比如想要创建sportsCar(跑车)的时候。

2

你想了解一下列表操作的基本知识:

$ 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 == j 的情况。j 是从 i+1 开始的。

撰写回答