Live data from Hacker News

Notset: A Do-Not-Care value for Python

github.com

11–20 of 41 posts

Re: Notset: A Do-Not-Care value for Python

#15
Everyone bumps into this at some time on their journey through Python, however personally it's not something I've contended with in years and there is good reason for that:

> Suppose you have a function which takes a person and allows you to update the person's name, age, both, or neither

The problem is not the lack of some fundamental feature, it is one of obviousness in interface design. A trixy interface as given by the example leads exactly to the kind of problems the library hopes to eliminate. Instead how about:

    def update(person, attrs):
        pass

    def update_with_email(person, attrs):
        update(person, attrs)
        send_email(person)
Not only is the problem avoided, but a problem of namespace pollution has been fixed too. Overusing keyword arguments in a hyper-generic manner forces extension of the code to require definition of a new function in order to avoid potential breakage.

For example, how does one add a 'use_html=True' parameter to update_with_email()? Perhaps by adding a 'use_html' kwarg that hopefully doesn't conflict with Person's attribute namespace, or perhaps by adding '_use_html', hoping to skirt the problem by introduction of ugliness. For a 'clean' backwards-compatible solution, we're forced into something like:

    def _real_update_with_email(person, use_html, kwargs):
        update(person, **kwargs)
        send_email(person, use_html=use_html)

    def update_with_email(person, **kwargs):
        _real_update_with_email(person, False, kwargs)

    def update_with_html_email(person, **kwargs):
        _real_update_with_email(person, True, kwargs)
How can the caller dynamically form the attribute names if they need to?

    # TODO: something seems terribly wrong here, I can't quite put my finger on it.
    update(person, **{'previous_' + attr: value})
etc.

I realize abuse of \* \* is very much a religious issue, and at first sight, one of the superficial attractions to Python (at least for me, way back in time), however with experience it seems to regularly introduce more problems than it solves outside a few niche uses. The idea of adding an 'undefined' value has been discussed going back years (try grepping python-ideas and python-dev) and it's never made it in for good reason.

There is one place where an 'undefined' might seem useful at first, for example in the implementation of `dict.pop()` where a missing second argument signals the need to raise KeyError. The problem is that no published, public value including 'undefined' can be used as placeholder without introducing another ugly rule to the language: the ability to use `pop(..., default)` with any default value except 'undefined'! (net simplicity gain: zero)

Re: Notset: A Do-Not-Care value for Python

#17
The problem with this idea, or rather its implementation, is that it's just a matter of time until someone uses NotSet as a legitimate value assigned to a variable/attribute, just like None is today. At this point someone will introduce a new singleton, "NotSetIReallyMeanItThisTime", and so on and so forth. It never ends.

The only way this might work is if NotSet (or whatever it's called) is a keyword and it is only allowed in (a) function signatures and (b) comparison with `is` and `is not`; everything else throws a syntax error.

Re: Notset: A Do-Not-Care value for Python

#19
I'm impressed by how much effort one can put into something that is effectively nothing else than:

    NotSet = type("NotSet", (object, ), dict(__repr__=lambda self: "NotSet"))
There is no amazing concept, no new idea or even anything remotely interesting at all here. This is but a side-effect of a type system that encourages the usage of None in this way and the fact that None is generally used to mean undefined in keyword arguments.

Why would anyone consider this notable, useful or even important enough to warrant an upvote?

Re: Notset: A Do-Not-Care value for Python

#20

Everyone bumps into this at some time on their journey through Python, however personally it's not something I've contended with in years and there is good reason for that: > Suppose you have a function which takes a person and allows you to update the person's name, age, both, or neither The problem is not the lack of some fundamental feature, it is one of obviousness in interface design. A trixy interface as given…

As a general rule of thumb (standard disclaimers apply), I've found it better to have several functions than one function, if that one function is going to do different operations according to the parameters passed in. ("Operation" is a vague term, but I think setting something vs not setting something would count.) It's all too common for the operation to end up being fixed at the call point, for every call point, and therefore for the path through each call to be the same each time. The parameter/argument system is the wrong mechanism for that.

This line of thinking was inspired by C's `fopen' (no doubt now that I've said that it's going to turn out that I'm the only person ever to have ended up using a string literal for the mode parameter 100% of the time). But I suspect it would be the case for this function too.

Post reply on HN