【问题标题】:Assign variable name to list in if statement python在if语句python中将变量名分配给列表
【发布时间】:2016-02-08 00:16:14
【问题描述】:

我为糟糕的标题道歉。不确定如何准确地表达我的问题。 我有下面的代码,它使用一个名为propadd 的元组列表。 if statement 测试元组的匹配条件。如果匹配只匹配到元组列表中的 1 个元组,它会执行与 if 语句中完全相同的代码,以便将此匹配的元组分配给变量 v,以便使用来自此匹配元组的值更新游标行。我想知道是否有办法摆脱在 if 语句之后将完全相同的代码分配给 v 的方法。在检查匹配长度时,是否可以在 if 语句中将列表分配给 v ?这是遵循此方法的大量代码的一部分。我相信这样做会让我的代码更快。

if len([item for item in propadd if item[0]==row1[8] and harversine(custx,custy,item[2],item[3])<1500]) == 1:
        v=[item for item in propadd if item[0]==row1[8] and harversine(custx,custy,item[2],item[3])<1500]
        row1[1]=v[0][1]
        row1[2]=v[0][2]
elif len([item for item in custadd if item[0]==row1[4]]) == 1:
        k=[item for item in custadd if item[0]==row1[4]]
        row1[1]=k[0][1]
        row1[2]=k[0][2]
elif len([item for item in numlist if re.search(r"^[0-9]+(?=\s)",row1[0]) is not None and item[0]==re.search(r"^[0-9]+(?=\s)",row1[0]).group()]) == 1
        m=[item for item in numlist if re.search(r"^[0-9]+(?=\s)",row1[0]) is not None and item[0]==re.search(r"^[0-9]+(?=\s)",row1[0]).group()]
        row1[1]=m[0][1]
        row1[2]=m[0][2]

【问题讨论】:

  • 如果你想让你的代码更快,我相信使用filter函数比list comp更快。在我打字的时候,@MadPhysicist 发布了我要说的内容:你不妨指定v 然后检查len(v),这样列表组合只运行一次
  • 我将研究filter 函数。谢谢。

标签: python list tuples arcpy


【解决方案1】:

它会让你的代码稍微快一点,更重要的是,更易读,更不容易出错。无论您创建的列表是否通过了测试len(...) == 1,它都会被计算出来。那么为什么不只计算一次呢?当然,您必须将elif 替换为else-if

# Compute v
v = [item for item in propadd if item[0]==row1[8] and harversine(custx,custy,item[2],item[3])<1500]
if len(v) == 1:
    row1[1]=v[0][1]
    row1[2]=v[0][2]
else:
    # If v fails, compute k
    k = [item for item in custadd if item[0]==row1[4]]
    if len(k) == 1:
        row1[1]=k[0][1]
        row1[2]=k[0][2]
    else:
        # If k fails, compute m
        m = [item for item in numlist if re.search(r"^[0-9]+(?=\s)",row1[0]) is not None and item[0]==re.search(r"^[0-9]+(?=\s)",row1[0]).group()]
        if len(m) == 1:
            row1[1]=m[0][1]
            row1[2]=m[0][2]

来自C,这比if(v = (....)) { } else ...麻烦多了。但是,还有另一种方法可以做到这一点。您可以使用列表推导中的每个表达式都是一个生成器这一事实:

v = (item for item in propadd if item[0]==row1[8] and harversine(custx,custy,item[2],item[3])<1500)
k = (item for item in custadd if item[0]==row1[4])
m = (item for item in numlist if re.search(r"^[0-9]+(?=\s)",row1[0]) is not None and item[0]==re.search(r"^[0-9]+(?=\s)",row1[0]).group())
for gen in (v, k, m):
    l = list(gen)
    if len(l) == 1:
        row1[1] = l[0][1]
        row1[2] = l[0][2]
        break

在这种情况下,表达式vkm 是生成器,它们是惰性求值的可迭代对象。他们实际上并没有计算列表。您可以遍历每一个并在找到时分配匹配的一个,而忽略其他的。直到语句 l = list(gen) 才计算列表。我认为第二种方法更加 Pythonic,因为无论您有多少条件,它都使用单个 for 循环,而不是离开页面的一系列 else 语句。

【讨论】:

  • 我还有 5 个其他 elif 用于检查 700,000 行的不同条件。在这种情况下,我必须在 if 和 elif 之外定义“v”。 (这些变量测试与此 v 不同的条件)。如果这些是为每一行计算的,那真的会减慢代码的速度,但我希望这些 v 变量仅在该行在第一个 if 和前面的 elifs 上失败时才计算,这样就不会每次都创建它们。
  • 您确实意识到如果len([item for item in propadd if item[0]==row1[8] and harversine(custx,custy,item[2],item[3])&lt;1500]) == 1 计算v 的值并将其传递给len()?我所做的只是将指向列表的指针分配给一个临时变量。
  • 另外,在你运行它并且知道有问题之前不要尝试优化你的代码。可读性比优化更重要。
  • 如果这不是您真正要问的问题,请发布您需要帮助的真实代码并再次提问。这可能是 XY 问题的一个例子。
  • 最后,您始终可以将elif 替换为合法的else-if 并仅在外部if 失败时预先计算elses 中的变量。
猜你喜欢
  • 2018-04-02
  • 1970-01-01
  • 2021-02-02
  • 1970-01-01
  • 2017-01-07
  • 2019-09-06
  • 2018-07-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多