基本方法链接

2024-03-28 14:57:01 发布

您现在位置:Python中文网/ 问答频道 /正文

我发现了这个method chaining in python,但即使有了它,我也无法理解Python中的方法链接。

这里的目标有两个:解决编码问题和理解方法链(考虑到我对可调用性仍然没有100%的信心)。

直到问题的定义。

我想要一个有两个方法的类:一个设置对象的参数'line',另一个覆盖到'bar'。

这就是我目前所得到的:

class foo():
    def __init__(self, kind=None):
        self.kind = kind

    def __call__(self, kind=None):
        return foo(kind=kind)

    def my_print(self):
        print (self.kind)

    def line(self):
        return self(kind='line')
    def bar(self):
        return self(kind='bar')

不幸的是,有了这些代码,我可以实现我的目标

a = foo()
a.bar().line().bar().bar().line().my_print()

但是我想通过编写这段代码得到同样的结果

a = foo()
a.bar.line.bar.bar.line.my_print()

我怎样才能做到这一点?我想我定义__call__方法的方式有问题。提前谢谢你的帮助。


Tags: 方法代码selfnone目标return定义foo
2条回答

方法链接只是能够将.second_func()添加到任何返回的.first_func()中。通过确保所有可链接的方法都返回self,它相当容易实现。(注意,这与__call()__无关)。

class foo():
    def __init__(self, kind=None):
        self.kind = kind
    def my_print(self):
        print (self.kind)
        return self
    def line(self):
        self.kind = 'line'
        return self
    def bar(self):
        self.kind='bar'
        return self

您可以通过忽略返回值以非链接方式使用foo对象:

a = foo()
a.line()
a.my_print()
a.bar()
a.my_print()

assert a.kind == 'bar'

或者,因为每个函数现在都返回对象本身,所以可以操作 直接返回值。可以将方法链接与此等效代码一起使用:

b = foo()
b.line().my_print().bar().my_print()
assert b.kind == 'bar'

甚至:

c = foo().line().my_print().bar().my_print()
assert c.kind == 'bar'

摆脱()调用语法的问题是一个完全独立于方法链的概念。如果您想要链属性,并让这些属性改变其对象,请使用@property装饰器。(但是通过一个属性改变对象似乎是危险的。例如,最好使用一个方法并用动词命名:.set_line(),而不是.line。)

class foo():
    def __init__(self, kind=None):
        self.kind = kind
    def my_print(self):
        print (self.kind)
        return self
    @property
    def line(self):
        self.kind = 'line'
        return self
    @property
    def bar(self):
        self.kind='bar'
        return self

a = foo()
a.line
a.my_print()
a.bar
a.my_print()

assert a.kind == 'bar'

b = foo()
b.line.my_print().bar.my_print()
assert b.kind == 'bar'

c = foo().line.my_print().bar.my_print()
assert c.kind == 'bar'

使用属性(描述符)。

class foo:
    def __init__(self, kind=None):
        self.kind = kind

    def __call__(self, kind=None):
        return foo(kind=kind)

    def my_print(self):
        print (self.kind)

    @property
    def line(self):
        return self(kind='line')

    @property
    def bar(self):
        return self(kind='bar')

不过,请注意,您没有覆盖任何内容,修改不会在本地工作(顺便说一句,这是很好的)。无论如何,对于大多数实际情况,这看起来不是一个好的设计选择,因为在某些情况下,您的方法将需要参数。

相关问题 更多 >