在Python(pymssql)中跳过键而不进行类型检查
我需要访问一个在Python(pymssql)中跳过键而不进行类型检查,python,typechecking,pymssql,Python,Typechecking,Pymssql,我需要访问一个dict的所有非整数键,它看起来像: result = { 0 : "value 1", 1 : "value 2", "key 1" : "value 1", "key 2" : "value 2", } 我目前正在通过以下方式进行此操作: headers = [header for header in tmp_dict.keys() if not isinstance
dict
的所有非整数键,它看起来像:
result = {
0 : "value 1",
1 : "value 2",
"key 1" : "value 1",
"key 2" : "value 2",
}
我目前正在通过以下方式进行此操作:
headers = [header for header in tmp_dict.keys() if not isinstance(header, int)]
我的问题:
tmp_dict
来自使用pymssql
和as_dict=True
属性的查询,出于某种原因,它返回所有包含预期数据的列名,但也包括由整数索引的相同数据。如何将查询结果作为只包含列值和数据的字典李>
谢谢你的帮助
PS-尽管我的问题可以通过回答2来解决,但我很好奇,如果不进行类型检查,怎么能做到这一点。主要针对那些说“永远不要进行类型检查”的人。查看pymssql(1.0.2)的源代码,很明显模块没有不生成整数索引数据的选项。但请注意,如果列名为空,则可以忽略按列名索引的数据
/* mssqldbmodule.c */
PyObject *fetch_next_row_dict(_mssql_connection *conn, int raise) {
[...]
for (col = 1; col <= conn->num_columns; col++) {
[...]
// add key by column name, do not add if name == ''
if (strlen(PyString_AS_STRING(name)) != 0)
if ((PyDict_SetItem(dict, name, val)) == -1)
return NULL;
// add key by column number
if ((PyDict_SetItem(dict, PyInt_FromLong(col-1), val)) == -1)
return NULL;
}
[...]
}
查看pymssql(1.0.2)的源代码,很明显模块没有不生成整数索引数据的选项。但请注意,如果列名为空,则可以忽略按列名索引的数据
/* mssqldbmodule.c */
PyObject *fetch_next_row_dict(_mssql_connection *conn, int raise) {
[...]
for (col = 1; col <= conn->num_columns; col++) {
[...]
// add key by column name, do not add if name == ''
if (strlen(PyString_AS_STRING(name)) != 0)
if ((PyDict_SetItem(dict, name, val)) == -1)
return NULL;
// add key by column number
if ((PyDict_SetItem(dict, PyInt_FromLong(col-1), val)) == -1)
return NULL;
}
[...]
}
这将删除重复的整数键输入
入口。我觉得你现在做的很好
这将删除重复的
整数键输入
入口。不过,我认为您所做的很好。关于您关于类型检查的问题,duck-type方法将是查看它是否可以转换为或用作int
def can_be_int(obj):
try:
int(obj)
except (TypeError, ValueError):
return False
return True
headers = [header for header in tmp_dict.keys() if not can_be_int(header)]
请注意,float
s可以通过截断它们来转换为int
s,因此这不一定完全等效
上面的一个细微变化是使用强制(0,obj)
代替int(obj)
。这将允许将任何类型的对象转换为具有整数的公共类型。您还可以执行类似于0+obj和1*obj
的操作,以检查可用于整数数学表达式的内容
您还可以检查其字符串表示形式是否都是数字:
headers = [header for header in tmp_dict.keys() if not str(header).isdigit()]
这可能更接近于不使用类型检查的解决方案,尽管它会更慢,当然,列名完全可能是仅为数字的字符串!(老实说,许多这样的方法都会失败。)
有时显式类型检查确实是最好的选择,这就是为什么该语言有允许您检查类型的工具。在这种情况下,我认为您很好,特别是因为结果字典被记录为只有整数和字符串作为键。您使用的方法是正确的,使用
isinstance()
而不是显式检查type()==int
关于类型检查的问题,duck-type方法是查看它是否可以转换为或用作int
def can_be_int(obj):
try:
int(obj)
except (TypeError, ValueError):
return False
return True
headers = [header for header in tmp_dict.keys() if not can_be_int(header)]
请注意,float
s可以通过截断它们来转换为int
s,因此这不一定完全等效
上面的一个细微变化是使用强制(0,obj)
代替int(obj)
。这将允许将任何类型的对象转换为具有整数的公共类型。您还可以执行类似于0+obj和1*obj
的操作,以检查可用于整数数学表达式的内容
您还可以检查其字符串表示形式是否都是数字:
headers = [header for header in tmp_dict.keys() if not str(header).isdigit()]
这可能更接近于不使用类型检查的解决方案,尽管它会更慢,当然,列名完全可能是仅为数字的字符串!(老实说,许多这样的方法都会失败。)
有时显式类型检查确实是最好的选择,这就是为什么该语言有允许您检查类型的工具。在这种情况下,我认为您很好,特别是因为结果字典被记录为只有整数和字符串作为键。通过使用
isinstance()
而不是显式地检查type()==int
来正确地进行操作as_dict=True
背后的基本原理是,您可以通过索引和名称进行访问。通常情况下,您会得到一个索引到的元组
,但出于兼容性原因,能够将dict
作为元组
索引,这意味着依赖于列编号的代码仍然可以工作,而不需要知道列名是可用的
def can_be_int(obj):
try:
int(obj)
except (TypeError, ValueError):
return False
return True
headers = [header for header in tmp_dict.keys() if not can_be_int(header)]
如果您只是使用result
检索列(按名称或索引),我不明白您为什么要删除它们?不管怎样,都要坚持下去。(除非出于某种原因,您计划在其他地方pickle或以其他方式持久化数据…)
不过,最好的过滤方法是使用isinstance
——在这种情况下,duck键入实际上是不和谐且效率低下的。例如:
names_only = dict( (k, v) for k,v in result.iteritems() if not isinstance(k, int) )
不要使用
尝试和除了舞蹈。使用as_dict=True
的基本原理是,您可以按索引和名称访问。通常情况下,您会得到一个索引到的元组
,但出于兼容性原因,能够将dict
作为元组
索引,这意味着依赖于列编号的代码仍然可以工作,而不需要知道列名是可用的
如果您只是使用result
检索列(按名称或索引),我不明白您为什么要删除它们?不管怎样,都要坚持下去。(除非出于某种原因,您计划在其他地方pickle或以其他方式持久化数据…)
不过,最好的过滤方法是使用isinstance
——在这种情况下,duck键入实际上是非音速的,而且