我应该将列表子类化还是创建带有列表作为属性的类? [英] Should I subclass list or create class with list as attribute?

查看:26
本文介绍了我应该将列表子类化还是创建带有列表作为属性的类?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要一个容器,它可以收集多个对象并提供有关容器元素的一些报告功能.基本上,我希望能够做到:

I need a container that can collect a number of objects and provides some reporting functionality on the container's elements. Essentially, I'd like to be able to do:

magiclistobject = MagicList()
magiclistobject.report()  ### generates all my needed info about the list content

所以我想到了将普通列表子类化并添加一个report()方法.这样,我就可以使用所有内置列表功能.

So I thought of subclassing the normal list and adding a report() method. That way, I get to use all the built-in list functionality.

class SubClassedList(list):
    def __init__(self):
        list.__init__(self)
    
    
    def report(self):      # forgive the silly example
        if 999 in self:
            print "999 Alert!"
        

相反,我也可以创建自己的具有 magiclist 属性的类,但是如果我想使用以下方法访问列表,我将不得不创建新的方法用于追加、扩展等:

Instead, I could also create my own class that has a magiclist attribute but I would then have to create new methods for appending, extending, etc., if I want to get to the list using:

magiclistobject.append() # instead of magiclistobject.list.append()

我需要这样的东西(这似乎是多余的):

I would need something like this (which seems redundant):

class MagicList():
    def __init__(self):
        self.list = []

    def append(self,element):
        self.list.append(element)

    def extend(self,element):
        self.list.extend(element)

# more list functionality as needed...
    
    def report(self):       
        if 999 in self.list:
            print "999 Alert!"

我认为对列表进行子类化是不费吹灰之力的.但是这里的这篇文章让它听起来像是一个禁忌.为什么?

I thought that subclassing the list would be a no-brainer. But this post here makes it sounds like a no-no. Why?

推荐答案

扩展列表可能不好的一个原因是因为它将您的MagicReport"对象与列表联系得太紧密.例如,一个 Python 列表支持以下方法:

One reason why extending list might be bad is since it ties together your 'MagicReport' object too closely to the list. For example, a Python list supports the following methods:

append
count
extend
index
insert
pop
remove
reverse
sort

它还包含大量其他操作(添加、使用 <> 进行比较、切片等).

It also contains a whole host of other operations (adding, comparisons using < and >, slicing, etc).

您的MagicReport"对象实际上想要支持所有这些操作吗?例如,以下是合法的 Python:

Are all of those operations things that your 'MagicReport' object actually wants to support? For example, the following is legal Python:

b = [1, 2]
b *= 3
print b   # [1, 2, 1, 2, 1, 2]

这是一个非常人为的例子,但如果你从list"继承,如果有人不小心做了这样的事情,你的MagicReport"对象也会做同样的事情.

This is a pretty contrived example, but if you inherit from 'list', your 'MagicReport' object will do exactly the same thing if somebody inadvertently does something like this.

再举一个例子,如果您尝试对 MagicReport 对象进行切片会怎样?

As another example, what if you try slicing your MagicReport object?

m = MagicReport()

# Add stuff to m

slice = m[2:3]
print type(slice)

您可能希望切片是另一个 MagicReport 对象,但它实际上是一个列表.您需要覆盖 __getslice__ 以避免出现意外行为,这有点麻烦.

You'd probably expect the slice to be another MagicReport object, but it's actually a list. You'd need to override __getslice__ in order to avoid surprising behavior, which is a bit of a pain.

它还使您更难更改 MagicReport 对象的实现.如果您最终需要进行更复杂的分析,那么将底层数据结构更改为更适合问题的结构通常会有所帮助.

It also makes it harder for you to change the implementation of your MagicReport object. If you end up needing to do more sophisticated analysis, it often helps to be able to change the underlying data structure into something more suited for the problem.

如果你对列表进行子类化,你可以通过提供新的appendextend等方法来解决这个问题,这样你就不会't 更改接口,但除非您通读整个代码库,否则您将没有任何明确的方法来确定实际使用了哪些列表方法.但是,如果您使用组合并仅将列表作为字段并为您支持的操作创建方法,那么您就会确切地知道需要更改哪些内容.

If you subclass list, you could get around this problem by just providing new append, extend, etc methods so that you don't change the interface, but you won't have any clear way of determining which of the list methods are actually being used unless you read through the entire codebase. However, if you use composition and just have a list as a field and create methods for the operations you support, you know exactly what needs to be changed.

实际上,我最近遇到了与您在工作中非常相似的情况.我有一个包含事物"集合的对象,我首先在内部将其表示为列表.随着项目要求的变化,我最终将对象更改为在内部使用 dict、自定义集合对象,最后是快速连续的 OrderedDict.至少根据我的经验,与继承相比,组合可以更轻松地更改某些内容的实现方式.

I actually ran into a scenario very similar to your at work recently. I had an object which contained a collection of 'things' which I first internally represented as a list. As the requirements of the project changed, I ended up changing the object to internally use a dict, a custom collections object, then finally an OrderedDict in rapid succession. At least in my experience, composition makes it much easier to change how something is implemented as opposed to inheritance.

话虽如此,我认为在您的MagicReport"对象除了名称之外的所有内容都是合法的列表的情况下,扩展列表可能没问题.如果您确实想以各种方式将 MagicReport 用作列表,并且不打算更改其实现,那么将列表子类化并完成它可能会更方便.

That being said, I think extending list might be ok in scenarios where your 'MagicReport' object is legitimately a list in all but name. If you do want to use MagicReport as a list in every single way, and don't plan on changing its implementation, then it just might be more convenient to subclass list and just be done with it.

尽管在这种情况下,最好只使用列表并编写报告"函数——我无法想象您需要多次报告列表的内容,并使用仅用于此目的的自定义方法可能会过大(尽管这显然取决于您究竟要做什么)

Though in that case, it might be better to just use a list and write a 'report' function -- I can't imagine you needing to report the contents of the list more than once, and creating a custom object with a custom method just for that purpose might be overkill (though this obviously depends on what exactly you're trying to do)

这篇关于我应该将列表子类化还是创建带有列表作为属性的类?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆