Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/286.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 比if更快的elif语句_Python_Python 2.x - Fatal编程技术网

Python 比if更快的elif语句

Python 比if更快的elif语句,python,python-2.x,Python,Python 2.x,我正在从传感器实时接收大量点。但是,我只需要4类点,即左上、右上、左下和右下。我在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

我正在从传感器实时接收大量点。但是,我只需要4类点,即左上、右上、左下和右下。我在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
每个点都有一个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
是否有任何有效的方法可以实现同样的目标

回答: 我正在添加从答案中得到的结果。这似乎是所有运动中最快的。下面是我的测试代码:

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

不要使用列表理解:

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

这样,您可以在一次迭代而不是两次迭代中完成所有工作。

而不是使用列表理解:

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

这样,您可以在一次迭代而不是两次迭代中完成所有操作。

您可以使用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

可以使用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

这里有一种应该更快的方法,因为它使用一个
if
来确定
是否是基于其
id
属性表示极值的点之一,再加上
if
操作中使用非常快速的字典
,以进行成员资格测试。基本上是这样做的
bbox
字典预先加载了对应于所寻找的四个ID的键,这使得检查其中任何一个ID都成为一个相对有效的操作

请注意,如果在
列表中有重复的
id
s点,则最后看到的一个点将是所选的点。还请注意,如果未找到具有匹配的
id
的点,则某些最终变量的值将为
None
,而不是
实例

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))

这里有一种应该更快的方法,因为它使用一个
if
来确定
是否是基于其
id
属性表示极值的点之一,再加上
if
操作中使用非常快速的字典
,以进行成员资格测试。基本上是这样做的
bbox
字典预先加载了对应于所寻找的四个ID的键,这使得检查其中任何一个ID都成为一个相对有效的操作

请注意,如果在
列表中有重复的
id
s点,则最后看到的一个点将是所选的点。还请注意,如果未找到具有匹配的
id
的点,则某些最终变量的值将为
None
,而不是
实例

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))


哪种方式有效?运行时、可读性或键入所需的时间?@NickPredey:Runtimes这是一个控制结构所能达到的效率,我想我应该为
按钮
id
->
按钮
映射使用字典。为什么要创建100个随机点,但只保留其中4个?哪种方式有效?运行时、可读性或键入所需的时间?@NickPredey:Runtimes这是一个控制结构所能达到的效率,我想我应该为
按钮
id
->
按钮
映射使用字典。为什么要创建100个随机点,但只保留其中4个?不幸的是,我无法控制此数组的索引。它可以是任何整数。请再核对一下这个问题。非常感谢。不幸的是,我无法控制此数组的索引。它可以是任何整数。请再核对一下这个问题。非常感谢。为什么要将字典限制在这些键上,而必须处理所有其他点id的异常?只需将每个Point.id添加到dict,并且只使用您感兴趣的键?您认为if-else块比异常处理快吗?我做了一个基准测试,它的速度是else block的两倍。不,只是用每个Point.id创建一个字典-不要限制它,并使用异常处理管理限制。后续代码可以只使用相关键而忽略另一个键。我们不知道有多少点,try/except块没有任何开销。try/except块没有用。无论如何,将在dict中添加密钥。你关于管理限制的声明很奇怪,因为它根本没有限制它。这让我思考。为什么要将字典限制在这些键上,而必须处理所有其他Point.id的异常?只需将每个Point.id添加到dict,并且只使用您感兴趣的键?您认为if-else块比异常处理快吗?我做了一个基准测试,它的速度是else block的两倍。不,只是用每个Point.id创建一个字典-不要限制它,并使用异常处理管理限制。后续代码可以只使用相关键而忽略另一个键。我们不知道有多少点,try/except块没有任何开销。try/except块没有用。无论如何,将在dict中添加密钥。你关于管理限制的声明很奇怪,因为它根本没有限制它。这让我想了想,非常感谢。我喜欢这种编码风格,尤其是
将bbox的值分配给具有有意义名称的变量。
非常感谢。我喜欢这种编码风格,尤其是
将bbox的值赋给具有有意义名称的变量。