我陷入了两难境地。我正在制作数百种不同类型的物体。一般来说,它们将是Food
,但主要是指定它是什么类型的食物。
class Food(object):
def __init__(self, taste = None):
self._taste = taste
class Bread(Food):pass
class Meat(Food):pass
class Soup(Food):pass
VS
class Food(object):
def __init__(self, isbread = False, ismeat = False, issoup = False):
self.is_bread = isbread
self.is_meat = ismeat
self.is_soup = issoup
然后我将比较那些对象,就像阵列中一个接一个地有两个面包一样。我想知道哪一个更符合OOP'的艺术,它可能更加pythonic。每次比较两个对象时,使用标志似乎比调用实例更快更容易。
答案 0 :(得分:1)
使用不同的类是更多的OOP和Pythonic。使用gflags只是意味着存储关于类型以外的类型的信息。
现在有趣的部分是以一种方式处理类型信息,使代码具有可读性和清晰性以及良好的性能。说实话,我会忽略后者而不是好的代码,直到它成为一个问题。
由于使用该类型的唯一示例是比较对象是否为同一类型,因此您最容易做到这一点:
type(bread1) == type(bread2)
您还可以创建方法或重载运算符来隐藏代码的大多数部分的机制,但最简单和最易读的内容在很大程度上取决于您的实际用例。
再举一个你在讨论中提到的例子:要比较任何面包是否相等,你可以这样做:
class Bread(Food):
def __eq__(self, other):
return isinstance(other, Bread)
像这样明确地执行它允许您拥有子类Baguette(Bread)
和Roll(Bread)
,其实例(都是面包)也将比较相等,它们与Bread
本身的任何实例相同。
答案 1 :(得分:0)
显然 第一个选项更加pythonic并且与OOP保持一致。
class Food(object):
def __init__(self, taste = None):
self._taste = taste
class Bread(Food):pass
class Meat(Food):pass
class Soup(Food):pass
这意味着所有Soup
,Meat
和Bread
对象都是Food
,并且具有共同的属性。
那么,您希望比较两个对象是否属于Food的同一子类。只需使用isinstance()
内置方法,然后检查是否True
。例如,
>>> bread = Bread()
>>> soup = Soup()
>>> isinstance(bread, Soup)
False
>>> isinstance(bread, soup.__class__)
False
>>> isinstance(bread, Bread)
True
如果您想使用==
运算符比较对象,只需覆盖__eq__
(等于)方法即可。如下所示
class Food(object):
def __init__(self, taste = None):
self._taste = taste
def __eq__(self, other):
return (isinstance(other, self.__class__)
然后你比较像这样的对象
>>> bread1 = Bread()
>>> bread2 = Bread()
>>> soup = Soup()
>>> bread1 == soup
False
>>> bread1 == bread2 #Are both breads?
True