什么是Python中被接受的数据对象的样式
什么是Python中被接受的数据对象的样式
在Python中,数据对象的正常风格是什么?假设我有一个方法从某个地方获取客户(网络、数据库等),我应该返回什么类型的对象?我看到有几种选择:\n
- \n
- 一个元组
- 一个字典
- 一个类实例(数据类是否“正常”)
\n
\n
\n
\n我相信还有其他选择。这是我做的第一个大型Python项目,所以我想从一开始就使用最佳实践。\n哇——对这个问题的负面反应感到惊讶。可能没有表达清楚。\n我有很多不同的数据项要在我的代码中传递。用户、产品、客户、订单...(实际上它们与此完全不同,但使用明显的类型更简单)。所以我有\n
def get_user(): return x
\nx应该是什么。一个名为user的类的实例,一个字典,一个元组...\n这些对象没有关联的方法,纯粹是数据。\n似乎命名元组是一个不错的选择。\n编辑:作为一种风格,这样怎么样?\n
class product: pass ... def get_product(): ... 从数据库读取的东西 pr = product() pr.name = dbthing[0] pr.price = dbthing[1] return pr
\n这是令人不悦、已经被广泛接受的风格还是奇怪的风格?它能工作。从消费者的角度来看,这样写出来的代码更易读。\n
def xxx(): pr = get_product() total = amount * pr.price
问题的出现原因:在Python中,有多种方式可以表示数据对象,比如使用namedtuples或者使用类。这给开发者带来了选择的困扰,不知道哪种方式是更好的和更被接受的方式。
解决方法:根据实际情况和需求来选择使用namedtuples还是类。如果需要提供给其他人使用的API,通常使用类会更好,因为类可以提供更友好的API并且可以更清晰地定义访问点。
此外,在代码示例中,最好在构造函数中传入参数,这样在“创建”对象时就可以返回一个真正可用的对象,而不是一个等待填充的空壳。从API的角度来看,如果类在没有设置一些值的情况下无法使用,则不应该有办法创建该类的实例而没有这些值已经设置。否则,你将不得不在很多地方编写繁琐的“如果没有设置,则失败”的代码来保护事物。尽管这在C++或Java等语言中更为真实,但遵循这种风格和操作模式仍然是一个很好的选择。
下面是整理后的文章:
在Python中,我们可以使用namedtuples或者类来表示数据对象。但是,到底使用哪种方式更好,更被接受呢?这取决于你在做什么以及是否需要为他人提供API。
对于API的提供,使用类通常会更友好,因为类可以提供更清晰的访问点。另外,如果可能的话,最好在类的构造函数中传入参数。这样,在“创建”对象时,就可以返回一个真正可用的对象,而不是一个等待填充的空壳。
从API的角度来看,如果类在没有设置一些值的情况下无法使用,则不应该有办法创建该类的实例而没有这些值已经设置。否则,你将不得不在很多地方编写繁琐的“如果没有设置,则失败”的代码来保护事物。
尽管这种风格和操作模式在C++或Java等语言中更为真实,但在Python中遵循这种风格仍然是一个很好的选择。因此,根据实际情况和需求,选择使用namedtuples还是类来表示数据对象。
在Python中,处理数据对象的一种常见方式是使用字典。然而,随着软件规模的增长,使用字典可能会导致代码变得混乱,因为很难准确地知道存在哪些键以及它们来自哪里。为了解决这个问题,有人提出了使用命名元组(namedtuple)的方法。命名元组是不可变的,因此在阅读代码时不必担心某个字段的值会发生改变。
然而,当我们需要为命名元组添加功能时,比如添加一个返回产品描述和价格的__unicode__方法,我们可以将其转换为一个普通的类。为了保持不可变性,我们可以通过继承命名元组来实现这个功能。例如,我们可以定义一个Product类,继承自命名元组Product,并在其中添加__unicode__方法,返回产品的描述和价格。
下面是一个示例代码:
from collections import namedtuple Product = namedtuple('Product', 'name price') class Product(Product): def __unicode__(self): return "{} (${})".format(self.name, self.price)
这样做的好处是,我们既能够享受命名元组的不可变性,又能够为其添加功能。如果我们需要将其转换为可变的类,只需将其中一个属性设置为可变的,或者在需要时将其转换为普通类即可。
使用命名元组是一种常见的处理数据对象的方式,它能够克服使用字典时的混乱问题,并提供不可变性。当需要为数据对象添加功能时,可以通过继承命名元组来实现。如果需要将其转换为可变的类,只需对其中一个属性进行相应的修改即可。
在Python中,有几种用于表示数据对象的接受的方式。关于如何选择合适的方式,可以从以下几个方面考虑:
首先,对于简单的数据记录,应该首先考虑使用collections.namedtuple
,如果由于某种原因不适用于该情况,则可以使用其他选项。一旦知道为什么不适用,通常就可以确定使用哪一种方式。
其次,举例来说,在使用ORM(对象关系映射)时,即使是最简单的记录也将被表示为对象。这是有充分理由的,因为它们都有一些共同的操作,比如将更改存储回数据库。ORM的教程/文档将指导你。如果直接使用Python的数据库API,则从SQL查询返回的行最初会以元组的形式返回,但一旦你拥有这些数据,你可以随意处理。此外,在调用execute()
返回它们之前,数据库连接器可以提供在其之前操作这些数据的方法,例如在sqlite3中设置行工厂。
再次,以“网络”为例。虽然存在许多数据交换的方式,但一个常见的例子是访问返回JSON数据的API。在这种情况下,最好将数据在程序中最初以JSON结构化的方式表示,即以包含列表、字典、字符串和数字的列表和字典的形式。一旦拥有数据,可以根据需要进行处理。通常可以直接使用数据,也可以立即将其重构为其他形式。个人偏好和特定情况会影响实际选择的方式。
总之,上述所有方式都可以作为可行的选择。一般来说,可以按照以下方式使用:
- 当每个位置都有自己的含义时,应使用元组。这就是为什么Python通过返回元组来从函数返回“多个值”的原因,因为这些不同的值可能是完全不同的类型,具有不同的含义。
- 当记录的可用键因记录而异时,应使用字典。
- 当每个记录的键相同时,应使用数据类。可以使用namedtuple
来表示不可变的记录。
- 当顺序重要但位置都是等价的时,应使用列表或元组。注意,这里有一点紧张之处,即“元组是不可变的,列表是可变的”与“元组用于异构数据,列表用于同构数据”之间的紧张关系。个人倾向于前者,但我也看到了对后者的合理论证,因此如果你想知道人们通常如何进行选择,就不能忽视这一点。
根据具体情况和个人喜好,可以选择适合的方式来表示数据对象。