【问题标题】:Versatile variables多功能变量
【发布时间】:2019-09-17 01:52:11
【问题描述】:

我想知道如何使变量与另一个变量一起相应地更改:

with open(csv_file, 'r', newline='') as csvfile:
    counter = csv.reader(csvfile, dialect='myDialect')
    counter = islice(counter, startatline, None)
    totalpendingtosend = sum(1 for row in counter if 'pending' in row)
csvfile.close()

with open(csv_file, 'r', newline='') as csvfile:
    counter = csv.reader(csvfile, dialect='myDialect')
    counter = islice(counter, startatline, None)
    totalconfirmedtosend = sum(1 for row in counter if 'confirmed' in row)
csvfile.close()

totaltosend = totalpendingtosend + totalconfirmedtosend

在这个示例中,我使用了两次相同的代码,因为 totalpendingtosend 和 totalconfirmedtosend 是硬编码的,但是有没有办法通过使用以下行:

statuses = ['confirmed', 'pending']
for i in statuses:
    with open(csv_file, 'r', newline='') as csvfile:
        counter = csv.reader(csvfile, dialect='myDialect')
        counter = islice(counter, startatline, None)
        total_?[i]?_tosend = sum(1 for row in counter if i in row)
    csvfile.close()

    totaltosend += total_?[i]?_tosend

我也可以以某种方式将通用硬编码变量更改为顶部列表中所写的内容?所以改变这个: ?[i]? 基本上相应地。有没有一种好方法可以做到这一点,以便我稍后也可以在我的代码中读出 totalpendingtosend 和 totalconfirmedtosend ?

提前感谢您的宝贵时间。

【问题讨论】:

  • 旁注:当您在with 块(上下文管理器)中打开文件时,之后无需close()with open(...) as 的全部意义在于最后自动清理。
  • 任何时候您想开始动态命名变量,请改用dict。从total_items_to_send = {} 开始,在你的 ???线路使用total_items_to_send[i]。或者,使用函数对代码进行重复数据删除:total_pending_to_send = how_many_to_send('pending', startatline); total_confirmed_to_send = how_many_to_send('confirmed', startatline)
  • 上面的好建议。您可能还想交换 withfor 以避免重复文件两次。更极端的建议是使用熊猫,那么整个例子就是一个班轮。
  • 谢谢@Amadan。我还没有真正体验过字典的全部潜力,所以我使用了一个简单的列表,其中包含一个 for 循环和条件语句来更改所需的变量。
  • @Marat,我真的不明白你交换forwith 的意思,以及它在更改我的代码时的作用。我已经更新了我使用的解决方案,其中还包含 forwith 语句。如果您有时间指出迭代问题是否仍然存在,我会很高兴。提前致谢。

标签: python variables


【解决方案1】:

我不得不稍微更新代码以获得想要的结果,这与问题无关。但至少这是完整的代码,如果其他人需要的话。

statuses = ['confirmed', 'pending']
totalconfirmedtosend, totalpendingtosend = 0, 0

for i in statuses:
    with open(csv_file, 'r', newline= '' ) as csvfile:
        counter = csv.reader(csvfile, dialect='myDialect')
        counter = islice(counter, startatline, None)

        for row in counter:
            ordernummer = (row[0] if not '.' in row[0] else row[0].split('.')[0]).strip()

            if i in row:
                with open('Sentalready_' + i + '.txt') as file:
                    alreadysent = False
                    l = []

                    for line in file:
                        alreadysent = line[:-1] == ordernummer
                        l.append(alreadysent)

                    ## Answer:
                    if i is 'confirmed':
                        if not any(l) == True:
                            totalconfirmedtosend += 1

                    elif i is 'pending':
                        if not any(l) == True:
                            totalpendingtosend += 1

如您所见,我所做的非常简单。在 for 循环中使用条件就可以了。我想知道这是否是最好的方法,但至少它将我的代码减半,我可以很容易地添加更多状态。感谢大家的帮助。

【讨论】:

    【解决方案2】:

    原答案

    是的,有办法。但是你不想使用它。

    您可以使用locals 以您想要的方式做您想做的事。但这种方式不是 Pythonic。

    代码会像这样丑陋:

    locals()["total_%s_tosend" % i] = sum(1 for row in counter if i in row)
    

    locals 返回一个字典,表示它运行的上下文中的局部变量。你可以阅读它们,你可以编写它们,你可以完全以编程方式创建新的局部变量。

    但这真的,真的,真的很丑,你不应该那样做。 相反,按照@Amadan 说的做:使用字典。

    PS:我有没有提到你不应该使用这个答案?

    更新

    上面的答案是错误的。我得到了纠正,我学到了一些新东西:

    Writing to locals() works in contrast to documentation saying its not(不,不是。不一定,至少……)

    感谢@user2357112 指出这一点。我会在这里留下答案,以便其他人从我的错误中吸取教训:)

    【讨论】:

    • "你可以阅读它们,你可以编写它们,你可以完全以编程方式创建新的局部变量。" - 不。不支持修改 locals(),在当前 CPython 中修改 fails in a function
    • 谢谢,@user。答案已更新以反映我的新知识:)
    猜你喜欢
    • 2021-04-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-07
    • 1970-01-01
    相关资源
    最近更新 更多