代码之家  ›  专栏  ›  技术社区  ›  ako

参数化的字符串格式会产生意外的结果

  •  1
  • ako  · 技术社区  · 7 年前

    我有一个dataframe,它包含一个微数据集的数据字典,包括字符串字段的字段宽度,这些字段是零填充的。

    我最终希望使用这个数据帧为每个要传递到数据库的变量创建一个转换器字典 pd.read_csv 调用,其中转换器函数lambdas是一个字符串格式化程序,其参数化宽度随每个变量而变化。

    换句话说,我想生成一个函数字典,每个函数都有自己的字符串格式模板,这样每个变量都可以在下游加载适当的零填充。

    • 为此,我对行进行迭代,并使用表示宽度的变量创建具有可变宽度的字符串格式化程序表达式。这似乎管用。

    • 我将此格式化程序存储在字典中,每行有一个条目。

    例子:

    # dict for storing the mapping
    coll={}
    
    # mock data (var name and associated width)
    df=pd.DataFrame(data={'nme':['a','b','c','d'],'width':[2,2,3,4]})
    
    # iterate rows
    for _,dta in df.iterrows():
    
        # create variable width format string from width variable
        # mix of old / new string format approach
    
        formatstring = ('{:0>%s}'%dta.width)
    
        # turn string into a function, with string to be padded as argument
    
        formatfunc = lambda x: formatstring.format(x)
        coll[dta.nme]=formatfunc
    
        print 'var {}; width {}'.format(dta.nme, dta.width)
        print formatstring
    

    var a; width 2
    {:0>2}
    var b; width 2
    {:0>2}
    var c; width 3
    {:0>3}
    var d; width 4
    {:0>4}
    

    但是当我在 coll

    coll['a'](3)
    '0003'
    

    在这里,我期望一个长度为2的键填充字符串 a . 相反,我得到了长度4。

    1 回复  |  直到 7 年前
        1
  •  1
  •   Qusai Alothman    7 年前

    这是因为lambda使用的是全局变量 formatstring 计算时。 格式化字符串 等于 {:0>4} ,上一次迭代中设置的值。

    另一个简单的例子:

    y = 5
    f = lambda x: print(x+y)
    f(2) # prints 7
    y = 10
    f(2) # prints 12
    


    如何解决这个问题

    解决这个问题的一个方法是完全去掉lambdas。一个不切实际的例子:

    df.set_index('nme',inplace=True)
    coll = df.to_dict(orient='index')   
    
    '0'*coll['a']['width']+str(3)  # prints '003'
    

    如果需要,可以将最后一行转换为函数(或lambda)。