Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/276.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 代理或子类化基类?_Python_Subclass_Proxy Classes - Fatal编程技术网

Python 代理或子类化基类?

Python 代理或子类化基类?,python,subclass,proxy-classes,Python,Subclass,Proxy Classes,这也许是一个过于笼统的问题,但它仍然困扰着我。一般来说,什么是更好的实践(为什么):代理或子类化基类?我所说的base是指一个标准类,它通常甚至没有用Python实现 一个更具体的问题如下:我希望为图边创建一个对象;图边本质上是一对两个顶点。顶点可以是任何可散列对象。我希望edge能够公开比frozenset公开更多的方法。所以我想知道我是否应该 class Edge(frozenset): def my_method(self, *args): return 3 或

这也许是一个过于笼统的问题,但它仍然困扰着我。一般来说,什么是更好的实践(为什么):代理或子类化基类?我所说的base是指一个标准类,它通常甚至没有用Python实现

一个更具体的问题如下:我希望为图边创建一个对象;图边本质上是一对两个顶点。顶点可以是任何可散列对象。我希望edge能够公开比
frozenset
公开更多的方法。所以我想知道我是否应该

class Edge(frozenset):
    def my_method(self, *args):
        return 3

第一种方法的好处是我必须写得更少(因为我不必复制所有原始方法)。然而,第二种方法在某种意义上看起来更安全。它也更灵活,因为它允许我避免一些
frozenset
公开的方法(如
difference
),如果我愿意的话

第一个方法还引入了传递的参数数量问题。如果我想控制它,我可能必须覆盖
冻结集。另一方面,第一种方法通常可能更快,因为代理会产生一些开销


我不知道这是否重要,但我通常为Python 2.7编写。

您必须问的问题是:
我的类是
还是
我的类有
?,即继承与组合的典型问题。换句话说,您的
Edge
frozenset
还是恰好有一个供内部使用

将其视为类的第三方用户。您将获得一个
对象。您可以看看它的API。你想在那里看什么?可能是允许您与
边缘
逻辑域交互的方法,例如,uhmm
.do\u what\u edges\u do()
,而不是像
.union()
.isdisjoint()
这样的事情

在这种情况下,我很清楚你应该选择作文。当有疑问时,就开始写作

但是,您可能希望直接在API中公开frozenset的一些方法。Python有很好的机制来实现这一点,但您必须区分普通的y方法和magic方法

常规方法

只需声明一个要公开的方法列表,然后使用
\uu getattr\uu
。例如,假设您想公开方法“abc”和“cde”(它们在
冻结集中不存在,这只是为了学习)

魔法方法:

前面的机制不适用于神奇的方法,Python为了提高性能而跳过它。在这种情况下,您必须明确声明它们。例如,一个有用的

class Edge(object):
  ..

  def __len__(self):
    return len(self._my_set)
阅读评论后编辑

你必须做出语义上的决定。我不知道边应该包含哪些对象,所以让我们假设
Item
objs。现在的问题是,您希望在代码的API中提供什么样的方法

  • 类似于
    get_items
    ?这强调了
    的概念。在这种情况下,返回一个集合(如用
    Item
    s填充的集合)是完全正确的。因为您说要向该集合添加更多方法,所以这可能不是您想要做的

  • 获取边缘
    ?这使得
    Edge
    的概念更加重要。在这种情况下,您应该返回自己的
    Edge
    类的实例。如果所有
    frozenset
    公开的方法对您的
    Edge
    概念有意义,那么就选择继承。否则,进行合成并仅公开有意义的内容(使用上述机制)


谢谢。然而,对我来说,这并不清楚。我相信,有一些更抽象思维的人会希望能够检查像
if edge1()&edge2()
(也就是说,
edge1
edge2
相交-作为集)。无论如何,对我来说,边是一个不变的集。但是,子类化
frozenset
仍然有很多麻烦,所以我不相信这是正确的做法。如果它只是一个集合,那么。。。使用一套。如果不需要特殊的含义或功能,为什么还要创建自己的类呢?我没说它只是一个集合。这是一个集合,但正如我在问题中所说的,它应该公开许多额外的方法。
class Edge(object):
  ..

  _exposed_methods = ['abc', 'cde']

  def __getattr__(self, item):
    if item in self._exposed_methods:
      return getattr(self, item)

    raise AttributeError
class Edge(object):
  ..

  def __len__(self):
    return len(self._my_set)