Python中在内层循环访问外层count变量及表结构转换问题
问题1:内层循环中外层count变量未正确递增的解决方法
先看你可能写出的错误代码示例:
funcs = [] for count in range(3): # 内层逻辑:把lambda加入列表,后续调用期望打印当前count值 funcs.append(lambda: print(count)) # 执行所有lambda for f in funcs: f() # 输出全是3,而非预期的0、1、2
问题原因:Python的循环变量属于整个循环的作用域,lambda表达式捕获的是变量的引用,而非迭代时的当前值。当后续调用lambda时,循环已经结束,count的值固定为最后一次迭代的结果(这里是3)。
解决方法:
- 方法1:用默认参数绑定当前值
默认参数会在lambda定义时就计算并绑定当前的count值,而非引用:
funcs = [] for count in range(3): funcs.append(lambda c=count: print(c)) for f in funcs: f() # 输出0、1、2
- 方法2:闭包包裹局部变量
通过嵌套函数创建独立局部作用域,捕获当前迭代的count值:
funcs = [] for count in range(3): def wrapper(c): return lambda: print(c) funcs.append(wrapper(count)) for f in funcs: f() # 输出0、1、2
- 方法3:使用
functools.partial
借助partial函数固定参数值:
from functools import partial funcs = [] for count in range(3): funcs.append(partial(print, count)) for f in funcs: f() # 输出0、1、2
问题2:数据库宽表转长表的实现
假设你的原始宽表结构(以MySQL为例):
CREATE TABLE wide_table ( id INT PRIMARY KEY, name VARCHAR(50), math_score INT, english_score INT, chinese_score INT );
目标长表结构:
CREATE TABLE long_table ( id INT, name VARCHAR(50), subject VARCHAR(20), score INT, PRIMARY KEY (id, subject) );
方式1:UNION ALL(通用SQL)
兼容绝大多数数据库的写法:
INSERT INTO long_table (id, name, subject, score) SELECT id, name, 'math' AS subject, math_score AS score FROM wide_table UNION ALL SELECT id, name, 'english' AS subject, english_score AS score FROM wide_table UNION ALL SELECT id, name, 'chinese' AS subject, chinese_score AS score FROM wide_table;
方式2:UNPIVOT(SQL Server、Oracle)
如果使用支持UNPIVOT语法的数据库,可简化代码:
SELECT id, name, subject, score FROM wide_table UNPIVOT ( score FOR subject IN (math_score, english_score, chinese_score) ) AS unpvt;
方式3:Python Pandas处理(数据已加载到内存时)
用pandas的melt方法快速实现宽转长:
import pandas as pd # 从数据库读取宽表数据 df_wide = pd.read_sql("SELECT * FROM wide_table", your_db_connection) # 执行宽转长 df_long = df_wide.melt( id_vars=['id', 'name'], # 保留的标识列 value_vars=['math_score', 'english_score', 'chinese_score'], # 需要转换的宽列 var_name='subject', # 转换后的科目列名 value_name='score' # 转换后的分值列名 ) # 清理科目名称(去掉_score后缀) df_long['subject'] = df_long['subject'].str.replace('_score', '') # 将结果写入数据库 df_long.to_sql('long_table', your_db_connection, if_exists='append', index=False)
内容的提问来源于stack exchange,提问作者Hmm
相关产品推荐
相关产品推荐

