比if-elif声明更快

时间:2017-10-29 16:33:57

标签: python python-2.x

我实时从传感器接收大量积分。但是,我只需要4类点,即top_left,top_right,bottom_left和bottom_right。我在Python 2中有一个if-elif语句如下:

from random import random, randint

# points below are received from sensor. however, 
# here in this post I am creating it randomly.
points = [Point(randint(0, i), random(), random(), random()) for i in range(100)] 

# 4 categories
top_left, top_right, bottom_left, bottom_right = None, None, None, None
for p in points:
    if p.id == 5:
        top_left = p
    elif p.id == 7:
        top_right = p
    elif p.id == 13:
        bottom_left = p
    elif p.id == 15:
        bottom_right = p

print top_left.id, top_left.x, top_left.y, top_left.z # check variable

每个Point都有一个id和x,y,z参数。这是一个内置课程。我只是在这里展示一个示例课程。

class Point():
    def __init__(self, id, x, y, z):
        self.id = id
        self.x = x
        self.y = y
        self.z = z

是否有任何有效的方法来考虑实现相同的运行时间。

答案: 我正在添加从答案中得到的结果。 the answer by Elis Byberi似乎是最快的。以下是我的测试代码:

class Point():
    def __init__(self, id, x, y, z):
        self.id = id
        self.x = x
        self.y = y
        self.z = z

from random import random, randint
n = 1000
points = [Point(randint(0, i), random(), random(), random()) for i in range(n)]

def method1():
    top_left, top_right, bottom_left, bottom_right = None, None, None, None
    for p in points:
        if p.id == 5:
            top_left = p
        elif p.id == 7:
            top_right = p
        elif p.id == 13:
            bottom_left = p
        elif p.id == 15:
            bottom_right = p
    #print top_left.id, top_left.x, top_left.y, top_left.z

def method2():
    categories = {
        5: None,  # top_left
        7: None,  # top_right
        13: None,  # bottom_left
        15: None  # bottom_right
    }

    for p in points:
        categories[p.id] = p

    top_left = categories[5]
    #print top_left.id, top_left.x, top_left.y, top_left.z

def method3():
    name_to_id = {'top_left': 5, 'top_right': 7, 'bottom_left': 13, 'bottom_right': 15}
    ids = [value for value in name_to_id.values()]
    bbox = {id: None for id in ids}

    for point in points:
        try:
            bbox[point.id] = Point(point.id, point.x, point.y, point.z)
        except KeyError:  # Not an id of interest.
            pass

    top_left = bbox[name_to_id['top_left']]
    #print top_left.id, top_left.x, top_left.y, top_left.z

from timeit import Timer
print 'method 1:', Timer(lambda: method1()).timeit(number=n)
print 'method 2:', Timer(lambda: method2()).timeit(number=n)
print 'method 3:', Timer(lambda: method3()).timeit(number=n)

请参阅下面的返回输出:

ravi@home:~/Desktop$ python test.py 
method 1: 0.174991846085
method 2: 0.0743980407715
method 3: 0.582262039185

3 个答案:

答案 0 :(得分:3)

您可以使用dict来保存对象。 Dict在密钥查找方面非常有效。

使用dict的速度是使用if else阻塞的两倍。

这是python中最有效的方法:

from random import random, randint

class Point():
    def __init__(self, id, x, y, z):
        self.id = id
        self.x = x
        self.y = y
        self.z = z

# points below are received from sensor. however,
# here in this post I am creating it randomly.
points = [Point(randint(0, i), random(), random(), random()) for i in
          range(100)]

# 4 categories
categories = {
    5: None,  # top_left
    7: None,  # top_right
    13: None,  # bottom_left
    15: None  # bottom_right
}

for p in points:
    categories[p.id] = p

>>> print categories[5].id, categories[5].x, categories[5].y, categories[5].z  # check variable
5 0.516239541892 0.935096344266 0.0859987803457

答案 1 :(得分:1)

而不是使用list-comprehension:

points = [Point(randint(0, i), random(), random(), random()) for i in range(100)]

使用循环并在创建过程中分配点:

points = []
for i in range(100):
    p = Point(randint(0, i), random(), random(), random())
    points.append(p)
    if p.id == 5:
        top_left = p
    elif p.id == 7:
       top_right = p
    elif p.id == 13:
        bottom_left = p
    elif p.id == 15:
        bottom_right = p

通过这种方式,您可以在一次迭代中完成所有操作,而不是两次。

答案 2 :(得分:1)

这是一种应该更快的方法,因为它使用单个if来确定Point是否是基于id属性代表极值的if之一,加上in {1}}使用非常快速的字典bbox操作进行成员资格测试。基本上做了什么,id字典预加载了与所寻求的四个ID相对应的键,这使得检查任何它们是一个相对有效的操作。

请注意,如果Point列表中存在重复id的点,则最后看到的点将是所选的点。另请注意,如果找不到匹配None的点,则某些最终变量的值为Point而不是from random import randint, random from pprint import pprint from operator import attrgetter class Point(): def __init__(self, id, x, y, z): self.id = id self.x = x self.y = y self.z = z points = [Point(randint(0, 20), random(), random(), random()) for i in range(100)] name_to_id = {'top_left': 5, 'top_right': 7, 'bottom_left': 13, 'bottom_right': 15} bbox = {id: None for id in name_to_id.values()} # Preload with ids of interest. for point in points: if point.id in bbox: # id of interest? bbox[point.id] = point # Assign bbox's values to variables with meaningful names. top_left = bbox[name_to_id['top_left']] top_right = bbox[name_to_id['top_right']] bottom_left = bbox[name_to_id['bottom_left']] bottom_right = bbox[name_to_id['bottom_right']] for point in [top_left, top_right, bottom_left, bottom_right]: print('Point({}, {}, {}, {})'.format(point.id, point.x, point.y, point.z)) 个实例。

play-services-auth
相关问题