Fluent interface with Python

南笙酒味 提交于 2020-06-25 05:36:49

问题


I have a Python function "send_message" which takes three arguments:

send_message("i like windmills", to="INBOX", from="OUTBOX")

I am thinking about putting a fluent interface on top of it. Ideally I'd like to write the following:

send_message("i like windmills").to("INBOX").from("OUTBOX")

or

send_message("i like windmills").from("OUTBOX").to("INBOX")

Update: The to() information is mandatory but the from() is not (as with real letters). So this one would also be a valid call:

send_message("i like windmills").to("INBOX")

Any ideas how to accomplish this or something similar?

The general approach of having methods of an object returning "self" is understood by me but in my understanding this would lead to something like this:

message = Message("i like windmills")
message.to("INBOX").from("OUTBOX").send()

But this one is not as nice as the previous example and I then would actually prefer the original version with the named arguments.

Any help is appreciated.


回答1:


It can be accomplished this way, I am unsure if there is a better way because this is my first attempt. Good luck!

DEFAULT_SENDER = 'my_address'
#Because the sender object is optional I assume you have a default sender

class Send_message(object):
    def __init__(self, message):
        self.message = message
        self.sender = None
        self.receiver = None
        self.method = None

    def to(self, receiver):
        self.receiver = receiver
        self.method = self.send()
        return self

    def _from(self, sender):
        self.sender = sender
        self.method = self.send()
        return self

    def __call__(self):
        if self.method:
            return self.method()
        return None

    def send(self):
        if self.receiver:
            if not self.sender:
                self.sender = DEFAULT_SENDER

            return lambda:actual_message_code(self.message, self.sender, self.receiver)


def actual_message_code(message, sender, receiver):
    print "Sent '{}' from: {} to {}.".format(message, sender, receiver)



Send_message("Hello")._from('TheLazyScripter').to('samba2')()
Send_message("Hello").to('samba2')._from('TheLazyScripter')()
Send_message("Hello").to('samba2')()

#Only change in actual calling is the trailing ()

By implementing the __call__ method we can tell the when we are at the end of the call chain. This of course adds the trailing () call. and requires you to change the pointer to your actual messaging method and default sender variable but I feel that this would be the simplest way to accomplish your goals without actually knowing when the chain ends.



来源:https://stackoverflow.com/questions/37827808/fluent-interface-with-python

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!