Python:类设计列表转换(评论我的代码)

2024-09-29 19:23:12 发布

您现在位置:Python中文网/ 问答频道 /正文

我一直在想一个对列表转换有用的类。 以下是我当前的实现:

class ListTransform(object):
    """Specs: stores original list + transformations.
    Transformations are stored in a list.
    Every transformation is a func call, with
    one parameter, transformations are done in place.
    """
    def __init__(self, _list):
        self.orig_list = _list
        self.reset()
    def addtransform(self,t):
        self.transforms.append(t)
    def reset(self, ts = []):
        self.transforms = ts
    def getresult(self):
        li = self.orig_list[:] # start from a copy from the original
        # call all the in-place transform functions in order
        for transform in self.transforms:
            transform(li)
        return li

def pick_transform(pickindexes):
    """Only includes elements with specific indexes
    """    
    def pt(li):
        newli = []
        for idx in pickindexes:
            newli.append(li[idx])
        del li[:] # clear all the elements
        li.extend(newli)
    return pt

def map_transform(fn_for_every_element):
    """Creates a transformation, which will call a specific
    function for every element in a list
    """
    def mt(li):
        newli = map(fn_for_every_element, li)
        del li[:] # clear
        li.extend(newli)
    return mt
# example:

# the object which stores the original list and the transformations
li = ListTransform([0,10,20,30,40,50,60,70,80,90])

# transformations
li.addtransform(map_transform(lambda x: x + (x/10)))
li.addtransform(pick_transform([5,6,7]))

# getting result, prints 55, 66, 77
print li.getresult() 

这很管用,然而,以不符合标准的方式实施某件事的感觉困扰着我。在

在这个实现中,您将使用哪些Python特性,我没有使用过?你会如何改进这门课的整体设计/理念?您将如何改进代码?

而且,由于重新发明轮子感觉很尴尬:什么是取代这个类的标准工具?

谢谢


Tags: theinselfforreturndeftransformli
3条回答

考虑到一般范围而不是特定的用例,我将以一种更“功能性”的方式来看待这一点:

  • 不要让转换到位,而是返回新的列表。这就是函数式编程中标准函数的工作原理(在Python中也是map()filter()和{})。

  • 专注于转换而不是数据。特别是,我根本不会创建像您的ListTransform这样的类,而是只创建一些可以链接的转换对象。

为了在代码中考虑函数编程,转换将只是函数,就像在您的设计中一样。除此之外,您还需要某种变换组合:

def compose(f, g):
    return lambda lst: f(g(lst))

(为了简单起见,给定的实现只有两个参数,而不是任意数字。)您的示例现在非常简单:

^{pr2}$

另一种方法是将转换实现为类而不是函数。在

您可以扩展list类本身,并在需要元素时延迟地应用转换。这里有一个简短的实现-它不允许对转换进行索引操作,但是您可以在堆栈中应用任何映射转换。在

class ListTransform(list):
    def __init__(self, *args):
        list.__init__(self, *args)
        self.transforms = []
    def __getitem__(self, index):
        return reduce(lambda item, t: t(item), self.transforms, list.__getitem__(self, index))
    def __iter__(self):
        for index in xrange(len(self)):
            yield self[index]
    def __repr__(self):
        return "'[%s]'" % ", ".join(repr(item) for item in self)
    __str__ = lambda s: repr(s).strip("'")

你准备好了:

^{pr2}$

好吧-我可能对getitem方法中的“reduce”调用反应过度了-但这是有趣的部分。:-) 为了便于阅读,请随意改写:

def __getitem__(self, index):
   item = list.__getitem__(self, index)
   for t in self.transforms:
       item = t(item)
   return item

如果您喜欢这个想法,您可以包含一个“filter”成员来为项创建筛选函数,并检查转换上的参数数量,以允许它们处理索引,甚至访问其他列表项。在

不要使用空列表作为默认参数。不使用并测试:

def some_method(self, arg=None):
    if arg is None:
        arg = []
    do_your_thing_with(arg)

我是一个众所周知的Python初学者陷阱。在

相关问题 更多 >

    热门问题