method chaining in python

前端 未结 4 541
故里飘歌
故里飘歌 2020-12-07 17:56

(not to be confused with itertools.chain)

I was reading the following: http://en.wikipedia.org/wiki/Method_chaining

My question is: what is the best

相关标签:
4条回答
  • 2020-12-07 18:26

    There isn't going to be any general way of allowing any method of any object to be chained, since you can't know what sort of value that method returns and why without knowing how that particular method works. Methods might return None for any reason; it doesn't always mean the method has modified the object. Likewise, methods that do return a value still might not return a value that can be chained. There's no way to chain a method like list.index: fakeList.index(1).sort() can't have much hope of working, because the whole point of index is it returns a number, and that number means something, and can't be ignored just to chain on the original object.

    If you're just fiddling around with Python's builtin types to chain certain specific methods (like sort and remove), you're better off just wrapping those particular methods explicitly (by overriding them in your wrapper class), instead of trying to do a general mechanism with __getattr__.

    0 讨论(0)
  • 2020-12-07 18:37

    There is a very handyPipe library which may be the answer to your question. For example::

    seq = fib() | take_while(lambda x: x < 1000000) \
                | where(lambda x: x % 2) \
                | select(lambda x: x * x) \
                | sum()
    
    0 讨论(0)
  • 2020-12-07 18:37

    It's possible if you use only pure functions so that methods don't modify self.data directly, but instead return the modified version. You also have to return Chainable instances.

    Here's an example using collection pipelining 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)))
    

    Use it like this:

    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]
    

    Note that .chain refers to itertools.chain and not the OP's chain.

    0 讨论(0)
  • 2020-12-07 18:44

    I was looking for something similar for chaining Class functions and found no good answer, so here is what I did and thought was a very simple way of chaining: Simply return the self object.

    So here is my setup:

    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
    

    And now I can name the car and put it in drive state by calling:

    my_car = Car()
    my_car.set_name('Porche').drive()
    

    Caveat: This only works on the class functions that do not intend to return any data.

    Hope this helps!

    0 讨论(0)
提交回复
热议问题