我正在寻找一种高效的,pythonic方式来搜索和更改对象列表。
问题很简单:咖啡对象有三个属性:名称(" Frapublabla"),颜色("深棕色")和味道("苦涩&#34) )。每种咖啡都有一个独特的名称,可能有多种颜色和口味。 Barista()提供有关新咖啡的信息。一旦Barista()完成提供n个咖啡,代码就会输出所有咖啡。
显而易见的迭代方法是:
Define <coffee> - a class with three properties: name, color, taste.
Define coffeeList = [] , tempNameList = []
For n times:
Get coffee name, color, taste from the user. Each time:
Search tempNameList for the name of the coffee.
If the coffee name is not there, then:
Create a new coffee object, add to coffeeList. The object includes name, color, and taste.
Add coffee name to tempNameList.
If the coffee name is found on tempNameList:
Iterate through the coffeeList to find the right coffee object. Then:
Add to that object another name or color.
这种方法不能很好地扩展。首先,每次添加咖啡时,我们都需要搜索整个coffeeList,获取每个对象的属性。
有更多的pythonic和优雅的方法来解决这个问题吗? collections.defaultdict()是我得到的最接近的,但似乎并不适用于这个问题。
答案 0 :(得分:0)
Defaultdicts肯定是这种方式的一种方式,但是,如果你试图采用面向对象的方法来解决问题,我个人的偏好是避免嵌套字典。这是一种潜在的pythonic解决方案。
import collections
class Coffee():
def __init__(self, name='', color='', taste=''):
self.name = name
self.color = color
self.taste = taste
def __repr__(self):
return '{0} {1} {2}'.format(self.name, self.color, self.taste)
prompt = "Enter name,color,taste or ctrl-d when done: "
coffees = collections.defaultdict(Coffee)
while True:
try:
name, color, taste = input(prompt).split(',')
coffees[name].name = name
coffees[name].color = color
coffees[name].taste = taste
except ValueError:
print("Try again!")
except EOFError:
print()
break
print(coffees)
〜
答案 1 :(得分:0)
我已尝试过三种不同的方法,如@Cyber,@ jme和@mdadm所述:(1)面向对象使用collections.defaultdict和(2)常规字典,和(3) )嵌套字典。时间结果几乎相同。我无法回答内存使用情况和其他CPU测量结果。由于可读性和OO性质,我和#1一起去。
以下是结果,以秒为单位。每个&#34;尝试&#34;迭代代码1M次。有20个随机生成的咖啡名称,每个咖啡有10种口味和10种颜色:
Try| Approach 1 | App 2 | App 3 |
+--+------------+-------|-------|
| 1| 41.1 | 42.1 | 42.1 |
| 2| 39.1 | 41.2 | 41.6 |
| 3| 38.6 | 41.1 | 40.1 |
| 4| 40.9 | 42.5 | 41.3 |
| 5| 39.5 | 40.1 | 39.7 |
代码如下。
方法1:
import collections, random, time
class Coffee():
def __init__(self):
self.name = name
self.color = set([])
self.taste = set([])
def __repr__(self):
return '{0} {1} {2}'.format(self.name, self.color, self.taste)
startTime = time.clock()
coffees = collections.defaultdict(Coffee)
for counter in range(1000000):
name = "Name_" + str(random.randint(1, 20))
taste = "taste_" + str(random.randint(1, 10))
color = "color_" + str(random.randint(1, 10))
coffees[name].name = name
coffees[name].taste.add(taste)
coffees[name].color.add(color)
print (time.clock() - startTime)
方法2:
import random, time
class Coffee():
def __init__(self, name, color, taste):
self.name = name
self.color = set([])
self.taste = set([])
def __repr__(self):
return '{0} {1} {2}'.format(self.name, self.color, self.taste)
startTime = time.clock()
coffeeList = {}
for counter in range(1000000):
name = "Name_" + str(random.randint(1, 20))
color = "color_" + str(random.randint(1, 10))
taste = "taste_" + str(random.randint(1, 10))
if name not in coffeeList:
coffeeObj = Coffee(name, color, taste)
coffeeList[name] = coffeeObj
else:
coffeeList[name].color.add(color)
coffeeList[name].taste.add(taste)
print (time.clock() - startTime)
方法3:
import random, time
coffeeNestedDict = {}
startTime = time.clock()
for counter in range(1000000):
name = "Name_" + str(random.randint(1, 20))
color = "color_" + str(random.randint(1, 10))
taste = "taste_" + str(random.randint(1, 10))
if name not in coffeeNestedDict:
coffeeNestedDict[name] = {"Color" : set([color]), "Taste" : set([taste])}
else:
coffeeNestedDict[name]["Color"].add(color)
coffeeNestedDict[name]["Taste"].add(taste)
print (time.clock() - startTime)