我应该子类化Python list还是使用list作为属性创建类? [英] Should I subclass Python list or create class with list as attribute?

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

问题描述

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

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]

这是一个非常人为的示例,但是,如果您从列表"继承,那么如果有人无意中执行了这样的操作,则"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等方法来解决此问题,以便不更改接口,但不会除非您通读了整个代码库,否则,可以使用任何明确的方法来确定实际使用的是哪种列表方法.但是,如果您使用组合,并且仅将列表作为字段并为支持的操作创建方法,那么您将确切知道需要更改的内容.

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)

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

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