0

我需要访问所有非整数键,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)]

我的问题:

  1. 有没有办法在没有类型检查的情况下做到这一点?
  2. tmp_dict是来自使用属性的查询pymssqlas_dict=True并且由于某种原因,它返回所有列名以及预期的数据,但还包括由整数索引的相同数据。如何将查询结果作为仅包含列值和数据的字典?

谢谢你的帮助!

PS - 尽管我的问题可能通过回答2得到解决,但我很好奇如何在没有类型检查的情况下完成此操作。主要针对那些说“永远不要进行类型检查”的人。

4

4 回答 4

1

查看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;
    }
    [...]
}

关于您的第一个问题,通过类型检查过滤结果集肯定是最好的方法。这正是当 as_dict 为 False 时 pymssql 返回数据的方式:

if self.as_dict:
    row = iter(self._source).next()
    self._rownumber += 1
    return row
else:
    row = iter(self._source).next()
    self._rownumber += 1
    return tuple([row[r] for r in sorted(row.keys()) if type(r) == int])
于 2012-07-18T16:35:33.233 回答
1

关于您关于类型检查的问题,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 将 s 转换为ints,因此这不一定完全等效。

上面的一个轻微变化是使用coerce(0, obj). int(obj)这将允许任何类型的对象可以转换为具有整数的通用类型。您还可以执行类似0 + obj and 1 * obj的操作来检查可以在整数数学表达式中使用的内容。

您还可以检查其字符串表示是否全为数字:

headers = [header for header in tmp_dict.keys() if not str(header).isdigit()]

这可能更接近于不使用类型检查的解决方案,尽管它会更慢,当然,列名完全有可能是一个只有数字的字符串!(老实说,其中许多方法都会失败。)

有时显式类型检查确实是最好的选择,这就是为什么该语言有工具可以让你检查类型。在这种情况下,我认为你很好,特别是因为结果字典被记录为只有整数和字符串作为键。而且您通过使用isinstance()而不是显式检查以正确的方式进行操作type() == int

于 2012-07-18T16:44:49.797 回答
1

背后的基本原理as_dict=True是您可以按索引和名称访问。通常你会得到tuple你的索引,但出于兼容性原因,能够索引 adict就好像它是一种tuple意味着取决于列号的代码仍然可以工作,而不知道列名是可用的。

如果您只是result用来检索列(按名称或索引),我不明白您为什么担心删除它们?不顾一切地继续。(除非出于某种原因您计划在其他地方腌制或以其他方式保存数据......)

但是,过滤掉它们的最好方法是使用isinstance- 在这种情况下,鸭子类型实际上是不符合 Python 且效率低下的。例如:

names_only = dict( (k, v) for k,v in result.iteritems() if not isinstance(k, int) )

而不是一个tryexcept跳舞。

于 2012-07-18T17:16:05.423 回答
0
>>> sorted(result)[len(result)/2:]
['key 1', 'key 2']

这将删除重复的integer-keyed条目。我认为你正在做的很好。

于 2012-07-18T16:36:36.447 回答