在python方法链接(method chaining in python)

2019-06-27 12:35发布

(不要与itertools.chain混淆)

我读了以下情况: http://en.wikipedia.org/wiki/Method_chaining

我的问题是: 什么是在Python中实现方法链的最佳方式?

这里是我的尝试:

class chain():
    def __init__(self, my_object):
        self.o = my_object

    def __getattr__(self, attr):
        x = getattr(self.o, attr)
        if hasattr(x, '__call__'):
            method = x
            return lambda *args: self if method(*args) is None else method(*args)
        else:
            prop = x
            return prop

list_ = chain([1, 2, 3, 0])
print list_.extend([9, 5]).sort().reverse()

"""
C:\Python27\python.exe C:/Users/Robert/PycharmProjects/contests/sof.py
[9, 5, 3, 2, 1, 0]
"""

一个问题是,如果在调用method(*args)修改self.o但不返回None 。 (那么我应该回到self或返回什么method(*args)返回)。

有没有人有实施链接的更好的方法? 可能有很多方法可以做到这一点。

如果我只是假设的方法总是返回None所以我可能总是返回self.o

Answer 1:

有一个非常方便的Pipe可能是回答你的问题库。 例如::

seq = fib() | take_while(lambda x: x < 1000000) \
            | where(lambda x: x % 2) \
            | select(lambda x: x * x) \
            | sum()


Answer 2:

这是可能的,如果你只使用纯函数 ,这样的方法没有修改self.data直接,而是返回修改后的版本。 你还必须返回Chainable实例。

下面是使用一个例子收集流水线处理列表:

import itertools

try:
    import builtins
except ImportError:
    import __builtin__ as builtins


class Chainable(object):
    def __init__(self, data, method=None):
        self.data = data
        self.method = method

    def __getattr__(self, name):
        try:
            method = getattr(self.data, name)
        except AttributeError:
            try:
                method = getattr(builtins, name)
            except AttributeError:
                method = getattr(itertools, name)

        return Chainable(self.data, method)

    def __call__(self, *args, **kwargs):
        try:
            return Chainable(list(self.method(self.data, *args, **kwargs)))
        except TypeError:
            return Chainable(list(self.method(args[0], self.data, **kwargs)))

使用这样的:

chainable_list = Chainable([3, 1, 2, 0])
(chainable_list
    .chain([11,8,6,7,9,4,5])
    .sorted()
    .reversed()
    .ifilter(lambda x: x%2)
    .islice(3)
    .data)
>> [11, 9, 7]

需要注意的是.chainitertools.chain而不是OP的chain



Answer 3:

这里不会是被链接允许任何对象的任何方法,任何普通的方式,因为你无法知道什么样的值方法返回,为什么不知道具体的方法是如何工作的。 方法可能会返回None任何理由; 它并不总是意味着该法修改的对象。 同样,也有一个返回值仍然方法可能不会返回可以链接的值。 有没有办法像链的方法list.indexfakeList.index(1).sort()不能有工作的很大希望,因为整点index是它返回一个数字,而且这个数字意味着什么,以及不可忽视的只是链条原来的对象。

如果你只是摆弄周围用Python的内建类型链某些特定的方法(比如排序和删除),你最好只是包装那些特定方法明确(通过在包装类中重写它们),而不是试图做一个与一般的机制__getattr__



文章来源: method chaining in python