Python : 链接命令

Python : Chaining commands

简洁的代码更漂亮。所以,我会选择

str_ = "Hello World    "
print str_.strip().replace(" ", "-").lower()

相比于:

str_ = "Hello World    "
str_ = str_.strip()
str_ = str_.replace(" ", "-")
str_ = str_.lower()
print str_

但是,在函数 returns 不兼容对象(例如 None)的情况下,这将不起作用。

案例:

set1 = set([1, 2, 3])
set2 = set([1, 3, 5])
set3 = set()
set3.update(set1) #returns None
set3.update(set2)
set3.update(set1.union(set2))
print len(set3)

我想知道是否也有任何方法可以像这样链接命令,也许是一些括号技巧?

集有就地方法,以及return一个对象的方法。 str 对象是不可变的,因此没有就地方法,所以只剩下 return 个新对象的方法。

set.update() 就地改变集合,所以你不能用它来链接,不。但是如果你使用 set.union() 而不是你会得到 完全相同的结果 ,但是作为 new 集:

set1 = set([1, 2, 3])
set2 = set([1, 3, 5])
print len(set1.union(set2))

set.union()也可以用|运算符表示:

print len(set1 | set2)

您可以根据需要链接这些链接:

print len(set1 | set2 | set3)

您可能会注意到,像 set.union() 这样的方法被列为可用于 set()frozenset() 类型,后者是不可变类型。但是,像 set.update() 这样的方法单独列出,仅适用于可变 set() 类型。

正如其他人所提到的,您经常可以使用 +| 等运算符获得您想要的结果。如果您更喜欢运算符链接但需要就地执行操作,您可以编写一个包装器 class 来完成它。

class Chainer(object):

    """A proxy object that allows an object's methods be chained even
    if the methods themselves to not return a reference to the object.
    When object methods return a reference to self, several calls can
    be made on the object as in `someobj.method1().method2()` and etc...
    """

    def __init__(self, target):
        """Create a chaining proxy to target"""
        self.target = target

    def __getattr__(self, attr):
        if attr == 'target':
            # let access to the proxied object through
            return self.__dict__['target']
        else:
            # get the proxied object attribute
            fctn = getattr(self.__dict__['target'], attr)
            if callable(fctn):
                # return a function that will call the proxied method, ignore
                # the return value and return a reference to the
                # proxy. The returned proxy can be used to call object
                # methods again.
                def caller(*args, **kw):
                    fctn(*args, **kw)
                    return self
                return caller
            else:
                return fctn


set1 = set([1, 2, 3])
set2 = set([1, 3, 5])
set3 = Chainer(set())
print len(set3.update(set1).update(set2).update(set1.union(set2)).target)