python中的方法链接

python中的方法链接,python,method-chaining,Python,Method Chaining,不要与itertools.chain混淆 我读了以下内容: 我的问题是:在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__'):

不要与itertools.chain混淆

我读了以下内容:

我的问题是:在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]
"""
一个问题是调用方法*args修改self.o但不返回None。那么我应该返回self还是返回method*args返回的内容

有谁有更好的实现链接的方法吗?可能有很多方法可以做到这一点


我是否应该假设一个方法总是返回None,这样我就可以总是返回self.o?

没有任何通用方法可以允许任何对象的任何方法被链接,因为在不知道特定方法如何工作的情况下,您无法知道该方法返回的值的类型以及原因。方法可能出于任何原因返回None;这并不总是意味着方法修改了对象。同样,返回值的方法可能仍然不会返回可链接的值。没有办法链接像list.index:fakeList.index1.sort这样的方法,因为index的关键是它返回一个数字,而这个数字意味着什么,不能忽略它只是链接到原始对象上

如果您只是摆弄Python的内置类型来链接某些特定方法,如sort和remove,那么最好通过在包装器类中重写这些方法来显式包装这些特定方法,这里有一个非常方便的库,可以回答您的问题,而不是试图用uu getattr uu做一个通用机制。

。例如:

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

如果您使用的方法不直接修改self.data,而是返回修改后的版本,那么这是可能的。您还必须返回可链接实例

下面是使用with lists的示例:

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]

注意.chain指的是itertools.chain,而不是OP的chain。

我正在寻找类似的链接类函数的方法,但没有找到好的答案,因此我做了以下工作,并认为这是一种非常简单的链接方法:只返回self对象

下面是我的设置:

Class Car():
    def __init__(self, name=None):
        self.name = name
        self.mode = 'init'

    def set_name(self, name):
        self.name = name
        return self

    def drive(self):
        self.mode = 'drive'
        return self
现在我可以通过调用以下命令来命名汽车并将其置于驾驶状态:

my_car = Car()
my_car.set_name('Porche').drive()
警告:这只适用于不打算返回任何数据的类函数


希望这有帮助

注意:我不确定python中是否应该使用方法链接,但我仍然感兴趣的是,您应该使用方法链接,这样方法就不会直接修改self.o,而是返回修改后的版本。另外,\uuuu getattr\uuuu应该返回一个chain实例。+1在习惯了C的LINQ之后,管道是我在Python中导入的第一件事。您需要小心使用from Pipe import*尽管如此,Pipe用于组合函数-将函数A的结果作为函数B的参数传递。链接通常是从多个调用返回相同的对象,以便在一个链中进行多个修改。JQuery已经普及了很多。但我相信链接不应该像JavaScript那样在Python中使用。谢谢,我之所以将其标记为正确,是因为我通过阅读pipe的源代码学到了一些很酷的东西。@robertking、@Kos、@BasicWolf请看下面这是pipe库的一个基本且简单得多的实现。谢谢-你说得对。我认为不可能是一般的。我能想到的最好的办法是让程序员决定他们是否想要链接。例如,默认情况下,它不返回self,它只返回方法返回的内容,但如果程序员显式地执行list_u.chain.sort,它可能会返回list_u,而不是None。@罗伯特金:对,一般的做法是,方法链接不是可以轻松附加到现有对象上的东西。基本上,你必须在设计一个类时考虑到方法链接,这样它才能正常工作。是的,这是有意义的——我认为链接只在控制自己状态但公开交互方法的对象上才有意义。在修改状态的过程之后,接收数据通常应该是一个单独的调用,否则就没有明确的抽象