传递集合参数而不解压缩其内容

Air*_*Air 8 python arguments iterable-unpacking

问题:编写一个__init__直接将集合作为参数而不是解压缩其内容的优缺点是 什么?

上下文:我正在编写一个类来处理数据库表中几个字段的数据.我遍历一些大的(约1亿行)查询结果,一次将一行传递给执行处理的类.每行作为元组从数据库中检索(或者可选地,作为字典).

讨论:假设我对三个字段感兴趣,但传递给我的类的内容取决于查询,查询由用户编写.最基本的方法可能是以下之一:

class Direct:
    def __init__(self, names):
        self.names = names

class Simple:
    def __init__(self, names):
        self.name1 = names[0]
        self.name2 = names[1]
        self.name3 = names[2]

class Unpack:
    def __init__(self, names):
        self.name1, self.name2, self.name3 = names
Run Code Online (Sandbox Code Playgroud)

以下是可能传递给新实例的行的一些示例:

good = ('Simon', 'Marie', 'Kent')                 # Exactly what we want
bad1 = ('Simon', 'Marie', 'Kent', '10 Main St')   # Extra field(s) behind
bad2 = ('15', 'Simon', 'Marie', 'Kent')           # Extra field(s) in front
bad3 = ('Simon', 'Marie')                         # Forgot a field
Run Code Online (Sandbox Code Playgroud)

面对上述情况时,Direct总是跑步(至少到此为止),但很可能是跑车(GIGO).它需要一个参数并将其完全按照给定的方式分配,因此这可以是任何大小的元组或列表,Null值,函数引用等.这是我可以想到的最快速和最脏的方式来初始化对象,但我觉得当我给它数据时,该类应该立即抱怨它显然不是为了处理而设计的.

Simplebad1正确处理,给出bad2时有错误,并在给出时抛出错误bad3.能够有效地截断输入bad1但不值得发生的错误是很方便的bad2.这个人感到天真和不一致.

Unpack似乎是最安全的方法,因为它会在所有三个"坏"情况下抛出错误.我们要做的最后一件事是用不好的信息静静地填充我们的数据库,对吧?它直接接受元组,但允许我将其内容标识为不同的属性,而不是强迫我继续引用索引,并且如果元组的大小错误则会抱怨.

另一方面,为什么要通过一个系列呢?因为我知道我总是想要三个字段,所以我可以定义__init__显式接受三个参数,并在将它传递给新对象时使用*-operator解包集合:

class Explicit:
    def __init__(self, name1, name2, name3):
        self.name1 = name1
        self.name2 = name2
        self.name3 = name3

names = ('Guy', 'Rose', 'Deb')
e = Explicit(*names)
Run Code Online (Sandbox Code Playgroud)

我看到的唯一区别是__init__定义有点冗长而且我们提高TypeError而不是ValueError当元组的大小错误时.从哲学上讲,似乎有意义的是,如果我们正在采集一些数据(一行查询)并检查其部分(三个字段),我们应该传递一组数据(元组)但存储它的部分(三个)属性).所以Unpack会更好.

如果我想接受一个不确定数量的字段,而不是总是三个,我仍然可以选择直接传递元组或使用任意参数列表(*args,**kwargs)和*-operator解包.所以我想知道,这是一个完全中立的风格决定吗?

Air*_*Air 5

通过尝试不同的方法并查看对您最有意义的内容以及阅读代码的其他人最容易理解的问题,可以最好地回答这个问题.

既然我有更多经验,我会问自己,我该如何计划获取这些价值?

当我访问此集合中的任何一个值时,我是否可能在同一子例程或代码段中使用大部分或全部值?如果是这样,"直接"方法是一个不错的选择 ; 它是最紧凑的,它让我把这个系列看作一个集合,直到我绝对需要注意内部的东西.

另一方面,如果我在这里使用了一些值,那里有一些值,我不希望在我可以直接引用值时,必须经常记住要访问哪个索引或以字典键的形式添加详细程度使用单独命名的属性.在这种情况下,我可能会避免使用"直接"方法,因此我只需要考虑在首次初始化类时有一个集合的事实.

其余每种方法都涉及将集合分成不同的属性,我认为这里明显的赢家是"明确"方法."简单"和"解包"方法共享隐藏的对集合顺序的依赖,而没有提供任何真正的优势.