簡體   English   中英

python 中的方法鏈接

[英]method chaining in python

(不要與 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

有一個非常方便的Pipe庫,它可能是您問題的答案。 例如::

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

如果您只使用純函數,則方法不會直接修改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]

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

我正在尋找類似的東西來鏈接Class函數,但沒有找到好的答案,所以這是我所做的並且認為是一種非常簡單的鏈接方式:只需返回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()

警告:這僅適用於不打算返回任何數據的類函數。

希望這可以幫助!

不會有任何通用方法允許鏈接任何對象的任何方法,因為您無法知道該方法返回什么樣的值以及為什么不知道該特定方法如何工作。 方法可能會因任何原因返回None 它並不總是意味着該方法已經修改了對象。 同樣,確實返回值的方法仍然可能不會返回可以鏈接的值。 沒有辦法鏈接像list.index這樣的方法: fakeList.index(1).sort()不能有太大希望工作,因為index的全部意義在於它返回一個數字,而這個數字意味着什么,並且不能僅僅為了鏈接到原始對象而被忽略。

如果您只是擺弄 Python 的內置類型來鏈接某些特定的方法(例如 sort 和 remove),那么最好只顯式地包裝這些特定的方法(通過在您的包裝類中覆蓋它們),而不是嘗試執行__getattr__一般機制。

關於什么

def apply(data, *fns):
    return data.__class__(map(fns[-1], apply(data, *fns[:-1]))) if fns else data

>>> print(
...   apply(
...     [1,2,3], 
...     str, 
...     lambda x: {'1': 'one', '2': 'two', '3': 'three'}[x], 
...     str.upper))
['ONE', 'TWO', 'THREE']
>>> 

..甚至保持類型:)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM