Python OOP:编写不同类对象之间关系的最佳方式

Python OOP:编写不同类对象之间关系的最佳方式,python,oop,Python,Oop,假设我们有两个类Basket和Item。每个篮子包含一个项目列表。我可以将项目的ids存储在篮子中,也可以直接将项目对象存储在篮子中。哪一个是最好的解决方案,为什么(在内存使用、covenience等方面) 案例A class Basket(object): def __init__(self, basket_name): self._name = basket_name self._items = [] def add_item(self,

假设我们有两个类
Basket
Item
。每个篮子包含一个项目列表。我可以将项目的
id
s存储在篮子中,也可以直接将项目对象存储在篮子中。哪一个是最好的解决方案,为什么(在内存使用、covenience等方面)

案例A

class Basket(object):

    def __init__(self, basket_name):
        self._name = basket_name
        self._items = []


    def add_item(self, item_id)
        self._items.append(item_id)


class Item(object):

    def __init__(self, item_id):
        self._id= item_id

>>> b = Basket('My_Basket')
>>> i1 = Item(1)
>>> i2 = Item(2)
>>> b.add_item(1)
>>> b.add_item(2)
案例B

class Basket(object):

    def __init__(self, basket_name):
        self._name = basket_name
        self._items = []


    def add_item(self, item)
        self._items.append(item)


class Item(object):

    def __init__(self, item_id):
        self._id= item_id


>>> b = Basket('My_Basket')
>>> i1 = Item(1)
>>> i2 = Item(2)
>>> b.add_item(i1)
>>> b.add_item(i2)

你应该直接储存物品。如前所述,这样做没有资源问题,然后它为篮子提供了对项目的直接访问。说你想知道这个篮子有多重?如果您向items类添加一个.weight方法,那么您可以让篮子遍历它包含的所有项并返回它们的权重

您应该直接存储项目。如前所述,这样做没有资源问题,然后它为篮子提供了对项目的直接访问。说你想知道这个篮子有多重?如果您向items类添加一个.weight方法,那么您可以让篮子遍历它包含的所有项并返回它们的权重

我更喜欢存储对象,而不是ID。因为每次你必须对你的物品做一些事情,你必须首先通过ID获取/加载这个对象。但这是一个一般情况


如果您有大量的项目,并且没有完整列表的操作(例如,basket只对单个对象执行操作,而不是对完整集合执行操作),您可能只希望存储ID。

我更希望存储对象,而不是ID。因为每次你必须对你的物品做一些事情,你必须首先通过ID获取/加载这个对象。但这是一个一般情况


如果您有大量的项目,并且没有完整列表的操作(例如,basket只对单个对象执行操作,而不是对完整集合执行操作),您可能只希望存储ID。

选项B通常是最佳选项,因为这是面向对象编程的工作方式。因为您直接使用对象,所以也可以在代码中直接访问它们。如果您使用链接选项,那么为了稍后访问给定的
,您必须执行某种查询来查找该对象。当您直接使用对象时,python本质上是为您创建链接。该对象不会复制两次,而是在
篮子
对象内的
\u items
列表中引用

此外,中的
self.\u id=item\u id

def __init__(self, item_id):
    self._id= item_id
不需要,因为您无需查找该id,因此:

>>>i1 = Item(1)
>>>i2 = Item(2)
只会变成:

>>> i1 = Item()
>>> i2 = Item()

选项B通常是最佳选项,因为这就是面向对象编程的工作方式。因为您直接使用对象,所以也可以在代码中直接访问它们。如果您使用链接选项,那么为了稍后访问给定的
,您必须执行某种查询来查找该对象。当您直接使用对象时,python本质上是为您创建链接。该对象不会复制两次,而是在
篮子
对象内的
\u items
列表中引用

此外,中的
self.\u id=item\u id

def __init__(self, item_id):
    self._id= item_id
不需要,因为您无需查找该id,因此:

>>>i1 = Item(1)
>>>i2 = Item(2)
只会变成:

>>> i1 = Item()
>>> i2 = Item()

python中的所有内容都是对象,包括用作其他对象ID的整数。因此,在案例A和案例B中,您都将对象的引用附加到
篮子中。_items
列表


那么A和B的区别是什么呢?如果只存储ID,那么如何引用原始对象?很难保证它们将存在于名称空间中。任何从
item
实例中查找属性的代码都可能落入该陷阱。

python中的所有内容都是对象,包括用作其他对象ID的整数。因此,在案例A和案例B中,您都将对象的引用附加到
篮子中。_items
列表


那么A和B的区别是什么呢?如果只存储ID,那么如何引用原始对象?很难保证它们将存在于名称空间中。任何从
实例中查找属性的代码都可能落入该陷阱。

我更喜欢案例B。否则,谁的工作是跟踪id?是否需要维护其他类作为数据库,以便通过对象的ID查找对象?将对象作为对象传递在语义上更有意义。在这种情况下,将
放入
篮子
比添加另一层间接寻址更“面向对象”。您的代码示例并不等效。无法访问片段A中具有
Basket
实例的
Item
实例,但在片段B中是可能的。python中的每个变量都是引用,因此您可以直接存储对象,而无需担心空间使用。关于便利性,这完全是你的需要。@ukaszRogalski当然,要使样品起作用,还需要其他方法。我并没有把它们编码成直截了当的。我更喜欢案例B。否则,谁的工作是跟踪身份证?是否需要维护其他类作为数据库,以便通过对象的ID查找对象?将对象作为对象传递在语义上更有意义。在这种情况下,将
放入
篮子
比添加另一层间接寻址更“面向对象”。您的代码示例并不等效。在代码段A中,无法访问具有
Basket
实例的
Item
实例,但在代码段B中是可能的。python中的每个变量都是引用,因此您可以直接存储对象,而无需担心