简体   繁体   English

在Python中拆分元组-最佳做法?

[英]Splitting tuples in Python - best practice?

I have a method in my Python code that returns a tuple - a row from a SQL query. 我的Python代码中有一个返回元组的方法-来自SQL查询的一行。 Let's say it has three fields: (jobId, label, username) 假设它具有三个字段:(jobId,label,username)

For ease of passing it around between functions, I've been passing the entire tuple as a variable called 'job'. 为了方便在函数之间传递它,我将整个元组作为一个名为“ job”的变量传递。 Eventually, however, I want to get at the bits, so I've been using code like this: (jobId, label, username) = job 最终,但是,我想了解一点,所以我一直在使用这样的代码:(jobId,label,username)= job

I've realised, however, that this is a maintenance nightmare, because now I can never add new fields to the result set without breaking all of my existing code. 但是,我已经意识到这是维护方面的噩梦,因为现在在不破坏所有现有代码的情况下,我永远无法在结果集中添加新字段。 How should I have written this? 我应该怎么写呢?

Here are my two best guesses: (jobId, label, username) = (job[0], job[1], job[2]) ...but that doesn't scale nicely when you have 15...20 fields 这是我的两个最佳猜测:(jobId,label,username)=(job [0],job [1],job [2])...但是当您有15 ... 20个字段时,缩放效果不佳

or to convert the results from the SQL query to a dictionary straight away and pass that around (I don't have control over the fact that it starts life as a tuple, that's fixed for me) 或者直接将SQL查询的结果转换为字典并传递给字典(我无法控制它作为元组开始的事实,这对我来说是固定的)

@Staale @Staale

There is a better way: 有一个更好的方法:

job = dict(zip(keys, values))

I'd say that a dictionary is definitely the best way to do it. 我想说字典绝对是最好的方法。 It's easily extensible, allows you to give each value a sensible name, and Python has a lot of built-in language features for using and manipulating dictionaries. 它易于扩展,允许您为每个值赋予一个合理的名称,并且Python具有许多内置的语言功能供使用和操作字典。 If you need to add more fields later, all you need to change is the code that converts the tuple to a dictionary and the code that actually makes use of the new values. 如果以后需要添加更多字段,则只需更改将元组转换为字典的代码以及实际使用新值的代码即可。

For example: 例如:

job={}
job['jobid'], job['label'], job['username']=<querycode>

This is an old question, but... 这是一个老问题,但是...

I'd suggest using a named tuple in this situation: collections.namedtuple 我建议在这种情况下使用命名元组: collections.namedtuple

This is the part, in particular, that you'd find useful: 这是特别有用的部分:

Subclassing is not useful for adding new, stored fields. 子类化对于添加新的存储字段没有用。 Instead, simply create a new named tuple type from the _fields attribute. 相反,只需从_fields属性创建一个新的命名元组类型。

Perhaps this is overkill for your case, but I would be tempted to create a "Job" class that takes the tuple as its constructor argument and has respective properties on it. 也许这对于您的情况而言是矫kill过正,但是我很想创建一个“ Job”类,该类将元组作为其构造函数参数并具有各自的属性。 I'd then pass instances of this class around instead. 然后,我将传递此类的实例。

An old question, but since no one mentioned it I'll add this from the Python Cookbook: 一个古老的问题,但是由于没有人提到,我将在Python Cookbook中添加它:

Recipe 81252: Using dtuple for Flexible Query Result Access 食谱81252:使用元组进行灵活的查询结果访问

This recipe is specifically designed for dealing with database results, and the dtuple solution allows you to access the results by name OR index number. 该配方是专门为处理数据库结果而设计的,并且元组解决方案允许您按名称或索引号访问结果。 This avoids having to access everything by subscript which is very difficult to maintain, as noted in your question. 如您的问题所述,这避免了必须通过很难维护的下标访问所有内容。

I would use a dictionary. 我会用字典。 You can convert the tuple to a dictionary this way: 您可以通过以下方式将元组转换为字典:

values = <querycode>
keys = ["jobid", "label", "username"]
job = dict([[keys[i], values [i]] for i in xrange(len(values ))])

This will first create an array [["jobid", val1], ["label", val2], ["username", val3]] and then convert that to a dictionary. 这将首先创建一个数组[[“ jobid”,val1],[“ label”,val2],[“ username”,val3]],然后将其转换为字典。 If the result order or count changes, you just need to change the list of keys to match the new result. 如果结果顺序或计数发生变化,则只需更改键列表以匹配新结果。

PS still fresh on Python myself, so there might be better ways off doing this. PS本身在Python上还很新鲜,因此可能会有更好的方法来做到这一点。

If you're using the MySQLdb package, you can set up your cursor objects to return dicts instead of tuples. 如果使用的是MySQLdb程序包,则可以设置光标对象以返回dict而不是元组。

import MySQLdb, MySQLdb.cursors
conn = MySQLdb.connect(..., cursorclass=MySQLdb.cursors.DictCursor)
cur = conn.cursor() # a DictCursor
cur2 = conn.cursor(cursorclass=MySQLdb.cursors.Cursor) # a "normal" tuple cursor

With a tuple it will always be a hassle to add or change fields. 对于元组,添加或更改字段总是很麻烦。 You're right that a dictionary will be much better. 没错,字典会更好。

If you want something with slightly friendlier syntax you might want to take a look at the answers this question about a simple 'struct-like' object. 如果您想要使用稍微友好的语法的内容,则可能需要看一下有关一个简单的“类似于结构的”对象的问题的答案。 That way you can pass around an object, say job , and access its fields even more easily than a tuple or dict: 这样,您可以绕过一个对象(例如job ,并且比元组或dict更轻松地访问其字段:

job.jobId, job.username = jobId, username

How about this: 这个怎么样:

class TypedTuple:
    def __init__(self, fieldlist, items):
       self.fieldlist = fieldlist
       self.items = items
    def __getattr__(self, field):
       return self.items[self.fieldlist.index(field)]

You could then do: 然后,您可以执行以下操作:

j = TypedTuple(["jobid", "label", "username"], job)
print j.jobid

It should be easy to swap self.fieldlist.index(field) with a dictionary lookup later on... just edit your __init__ method! 稍后将self.fieldlist.index(field)与字典查找交换self.fieldlist.index(field)应该很容易...只需编辑__init__方法! Something like Staale does. 像Staale一样。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM