Couldn't you build up a dictionary of keyword arguments instead and do all the validation in the __init__ method? E.g.
kwargs = {}
if is_full_moon() and wind_direction == EAST:
kwargs["baz"] = 42
thing = Thing(foo=3.14, bar=1, **kwargs)
Couldn't you build up a dictionary of keyword arguments instead and do all the validation in the __init__ method? E.g.
kwargs = {}
if is_full_moon() and wind_direction == EAST:
kwargs["baz"] = 42
thing = Thing(foo=3.14, bar=1, **kwargs)
Builders have some neat properties like partial evaluation, which becomes especially neat when you use stateless builders that return new instances. They can also be subclassed, allowing not only behavior that can be overridden at individual method granularity, but able to build a different subclass.
Obviously don't reach for a builder if you don't have these use cases though.