[Python-ideas] "Immutable Builder" Pattern and Operator

M.-A. Lemburg mal at egenix.com
Mon Jan 23 08:18:18 EST 2017


On 23.01.2017 14:05, Soni L. wrote:
> 
> 
> On 23/01/17 09:45 AM, Serhiy Storchaka wrote:
>> On 23.01.17 01:30, Soni L. wrote:
>>> On 22/01/17 08:54 PM, Serhiy Storchaka wrote:
>>>> On 23.01.17 00:45, Soni L. wrote:
>>>>> I've been thinking of an Immutable Builder pattern and an operator
>>>>> to go
>>>>> with it. Since the builder would be immutable, this wouldn't work:
>>>>>
>>>>> long_name = mkbuilder()
>>>>> long_name.seta(a)
>>>>> long_name.setb(b)
>>>>> y = long_name.build()
>>>>
>>>> I think the more pythonic way is:
>>>>
>>>> y = build(a=a, b=b)
>>>>
>>>> A Builder pattern is less used in Python due to the support of keyword
>>>> arguments.
>>>
>>> I guess you could do something like this, for an IRC bot builder:
>>>
>>> fnircbotbuilder = mkircbotbuilder(network="irc.freenode.net", port=6697,
>>> ssl=true)
>>> mainbot = mkircbotbuilder(parent=fnircbotbuilder,  # ???
>>>                           channels=["#bots"]).build()
>>> fndccbotbuilder = mkircbotbuilder(parent=fnircbotbuilder, dcc=true,
>>> channeldcc=true)
>>> dccbot = mkircbotbuilder(parent=fndccbotbuilder,
>>> channels=["#ctcp-s"]).build()
>>> otherircbotbuilder = mkircbotbuilder(parent=fndccbotbuilder,
>>> network="irc.subluminal.net")  # because we want this whole network
>>> otherbot = mkircbotbuilder(parent=otherircbotbuilder,
>>> channels=["#programming"]).build()    # to use DCC and channel DCC
>>>
>>> But this would be cleaner:
>>>
>>> botbuilder =
>>> mkircbotbuilder().network("irc.freenode.net").port(6697).ssl(true)
>>> mainbot = botbuilder.channels(["#bots"]).build()
>>> botbuilder .= dcc(true).channeldcc(true)
>>> dccbot = botbuilder.channels(["#ctcp-s"]).build()
>>> botbuilder .= network("irc.subluminal.net")
>>> otherbot = botbuilder.channels(["#programming"]).build()
>>
>> In Python you can save common options in a dict and pass them as
>> var-keyword argument. Or use functools.partial. In any case you don't
>> need a builder class with the build method and a number of configuring
>> methods. It can be just a function with optional keyword parameters.
>>
>> A Builder pattern is often used in languages that don't support
>> passing arguments by keyword and partial functions. Python rarely
>> needs the purposed class implementing a Builder pattern. Actually a
>> Builder pattern is built-in in the language as a part of syntax.
>>
> Yeah but the dotequals operator has many other benefits:
> 
> long_name .= __call__  # cast to callable
> long_name .= wrapped  # unwrap
> etc
> 
> And it also looks neat.

I don't see this an being a particular intuitive way of writing
such rather uncommon constructs.

The syntax is not clear (what if you have an expression on the RHS)
and it doesn't save you much in writing (if long_name is too long
simply rebind it under a shorter name for the purpose of the code
block).

Also note that rebinding different objects to the same name
in the same block is often poor style and can easily lead to
hard to track bugs.

-- 
Marc-Andre Lemburg
eGenix.com

Professional Python Services directly from the Experts (#1, Jan 23 2017)
>>> Python Projects, Coaching and Consulting ...  http://www.egenix.com/
>>> Python Database Interfaces ...           http://products.egenix.com/
>>> Plone/Zope Database Interfaces ...           http://zope.egenix.com/
________________________________________________________________________

::: We implement business ideas - efficiently in both time and costs :::

   eGenix.com Software, Skills and Services GmbH  Pastor-Loeh-Str.48
    D-40764 Langenfeld, Germany. CEO Dipl.-Math. Marc-Andre Lemburg
           Registered at Amtsgericht Duesseldorf: HRB 46611
               http://www.egenix.com/company/contact/
                      http://www.malemburg.com/



More information about the Python-ideas mailing list