与 Python 的流畅界面
Fluent interface with Python
我有一个 Python 函数“send_message”,它接受三个参数:
send_message("i like windmills", to="INBOX", from="OUTBOX")
我正在考虑在它上面放一个流畅的界面。理想情况下,我想写以下任何内容:
send_message("i like windmills").to("INBOX").from("OUTBOX")
send_message("i like windmills").from("OUTBOX").to("INBOX")
# 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")
有什么想法可以完成这个或类似的事情吗?
我理解让对象的方法返回“self”的一般方法,但根据我的理解,这会导致这样的事情:
message = Message("i like windmills")
message.to("INBOX").from("OUTBOX").send()
但是这个不如前面的例子好,所以我实际上更喜欢带有命名参数的原始版本。
感谢任何帮助。
可以这样实现,第一次尝试不知道有没有更好的方法。祝你好运!
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 ()
通过实施 __call__
方法,我们可以知道我们何时处于调用链的末尾。这当然会添加尾随 ()
调用。并要求您更改指向实际消息传递方法和默认发件人变量的指针,但我认为这是在不知道链何时结束的情况下实现目标的最简单方法。
returning self
有一个缺点。改变其中一个变量会影响另一个变量。这是一个例子
取自@TheLazyScripter 代码,但修改了示例。
a = Send_message("Hello")
b = a
a = a._from('theLazyscripter')
b = b._from('Kracekumar').to('samba 2')
b()
a.message = 'Hello A'
a.to('samba2')()
b.to('samba 2')()
Send_message("Hello").to('samba2')._from('TheLazyScripter')()
Send_message("Hello").to('samba2')()
a和b变量指向同一个实例。修改一个值会影响其他值。查看输出的第二行和第三行。
输出
Sent 'Hello' from: Kracekumar to samba 2.
Sent 'Hello A' from: Kracekumar to samba2.
Sent 'Hello A' from: Kracekumar to samba 2.
Sent 'Hello' from: TheLazyScripter to samba2.
Sent 'Hello' from: my_address to samba2.
b=a
和修改 a
的内容会影响 b
的值。
如何去除这个副作用?
而不是 returning self
return 一个新实例来消除副作用。
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 _clone(self):
inst = self.__class__(message=self.message)
inst.sender = self.sender
inst.receiver = self.receiver
inst.method = self.method
return inst
def to(self, receiver):
self.receiver = receiver
self.method = self.send()
return self._clone()
def _from(self, sender):
self.sender = sender
self.method = self.send()
return self._clone()
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))
a = Send_message("Hello")
b = a
a = a._from('theLazyscripter')
b = b._from('Kracekumar').to('samba 2')
b()
a.message = 'Hello A'
a.to('samba2')()
b.to('samba 2')()
Send_message("Hello").to('samba2')._from('TheLazyScripter')()
Send_message("Hello").to('samba2')()
_clone
方法每次都会创建实例的新副本。注意:当其中一个值是列表或字典时,需要调用深拷贝。这里是字符串,因此不需要。但是思路还是一样的,复制之前的每个属性returning.
输出
Sent 'Hello' from: Kracekumar to samba 2.
Sent 'Hello A' from: theLazyscripter to samba2.
Sent 'Hello' from: Kracekumar to samba 2.
Sent 'Hello' from: TheLazyScripter to samba2.
Sent 'Hello' from: my_address to samba2.
输出行号 2
和 3
清楚地表明新代码中没有副作用。
我写了一篇关于 Fluent Interface
的博客 post
我有一个 Python 函数“send_message”,它接受三个参数:
send_message("i like windmills", to="INBOX", from="OUTBOX")
我正在考虑在它上面放一个流畅的界面。理想情况下,我想写以下任何内容:
send_message("i like windmills").to("INBOX").from("OUTBOX")
send_message("i like windmills").from("OUTBOX").to("INBOX")
# 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")
有什么想法可以完成这个或类似的事情吗?
我理解让对象的方法返回“self”的一般方法,但根据我的理解,这会导致这样的事情:
message = Message("i like windmills")
message.to("INBOX").from("OUTBOX").send()
但是这个不如前面的例子好,所以我实际上更喜欢带有命名参数的原始版本。
感谢任何帮助。
可以这样实现,第一次尝试不知道有没有更好的方法。祝你好运!
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 ()
通过实施 __call__
方法,我们可以知道我们何时处于调用链的末尾。这当然会添加尾随 ()
调用。并要求您更改指向实际消息传递方法和默认发件人变量的指针,但我认为这是在不知道链何时结束的情况下实现目标的最简单方法。
returning self
有一个缺点。改变其中一个变量会影响另一个变量。这是一个例子
取自@TheLazyScripter 代码,但修改了示例。
a = Send_message("Hello")
b = a
a = a._from('theLazyscripter')
b = b._from('Kracekumar').to('samba 2')
b()
a.message = 'Hello A'
a.to('samba2')()
b.to('samba 2')()
Send_message("Hello").to('samba2')._from('TheLazyScripter')()
Send_message("Hello").to('samba2')()
a和b变量指向同一个实例。修改一个值会影响其他值。查看输出的第二行和第三行。
输出
Sent 'Hello' from: Kracekumar to samba 2.
Sent 'Hello A' from: Kracekumar to samba2.
Sent 'Hello A' from: Kracekumar to samba 2.
Sent 'Hello' from: TheLazyScripter to samba2.
Sent 'Hello' from: my_address to samba2.
b=a
和修改 a
的内容会影响 b
的值。
如何去除这个副作用?
而不是 returning self
return 一个新实例来消除副作用。
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 _clone(self):
inst = self.__class__(message=self.message)
inst.sender = self.sender
inst.receiver = self.receiver
inst.method = self.method
return inst
def to(self, receiver):
self.receiver = receiver
self.method = self.send()
return self._clone()
def _from(self, sender):
self.sender = sender
self.method = self.send()
return self._clone()
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))
a = Send_message("Hello")
b = a
a = a._from('theLazyscripter')
b = b._from('Kracekumar').to('samba 2')
b()
a.message = 'Hello A'
a.to('samba2')()
b.to('samba 2')()
Send_message("Hello").to('samba2')._from('TheLazyScripter')()
Send_message("Hello").to('samba2')()
_clone
方法每次都会创建实例的新副本。注意:当其中一个值是列表或字典时,需要调用深拷贝。这里是字符串,因此不需要。但是思路还是一样的,复制之前的每个属性returning.
输出
Sent 'Hello' from: Kracekumar to samba 2.
Sent 'Hello A' from: theLazyscripter to samba2.
Sent 'Hello' from: Kracekumar to samba 2.
Sent 'Hello' from: TheLazyScripter to samba2.
Sent 'Hello' from: my_address to samba2.
输出行号 2
和 3
清楚地表明新代码中没有副作用。
我写了一篇关于 Fluent Interface
的博客 post