Hacker Newsnew | past | comments | ask | show | jobs | submit | shmeedogg's commentslogin

Agreed, I think the distinction between a bound method or a function is irrelevant here.

If we want explicit kwargs (a big 'if' since many of the suggestions in this thread are to give up on that idea), then we need some value to distinguish it from None.


I'd love to see this integrated into the language and live along side of `None` (I can dream, can't I?)

But until then, how can two different libraries agree to use the exact same instance of `NotSet` without some standard package defining it?

The goal is really to be able to 'proxy' this do-not-care condition from applications into libraries in a standardized way.


I'll repeat my advice to take this to the python-ideas mailing list. You'll get real reasons why this shouldn't (or should) be included in __builtins__.

As far as two libraries agreeing on using the same instance, one can define it the way you've done with `NotSet = object()`, and they can both use it just like they share any other named object (classes, functions, constants, sentinels). Better yet, it can carry a more meaningful name when "NotSet" doesn't really describe how they're using the sentinel.


To my ear, this does sound the best. Thanks for the suggestion!


Interesting. I love the idea of not having to import an external library, but much like the `NotImplementedError` suggestion, it overloads a value that already has a specific meaning, in this case related to slice-notation.

I'd worry that this approach could end up being even more confusing.


Yeah it is a hack but in 6 or 7 years of using Python I haven't once needed to use Ellipsis for its intended purpose. I always end up using it though for "not set" where None is one of the valid set values.


> whereas a function with a signature will need its arguments changed whenever the database schema changes.

True there is some work in keeping the two synchronized, but there are benefits.

First, unexpected arguments are immediately caught since they throw a TypeError.

Without this, you either have to manually check for unexpected keys (probably doing a set difference with `allowed_keys` or something) or you just silently pass through unrecognized attributes, probably causing strange behavior later on.

Second, you are forced to say explicitly which attributes are modifiable. To draw from the 'person' example, `name` and `age` might be modifiable, but `admin` might be protected. That would be made abundantly clear by `update(person, name=NotSet, age=NotSet)`, but less so, by `update(person, attrs)` or `update(person, kwargs)`.

A clear docstring would help, but I'd prefer to have the code just fail-fast on this unexpected input.


> First, unexpected arguments are immediately caught since they throw a TypeError.

> Without this, you either have to manually check for unexpected keys (probably doing a set difference with `allowed_keys` or something) or you just silently pass through unrecognized attributes, probably causing strange behavior later on.

The default constructor for SQLAlchemy declarative base does a simple check for unexpected keys, and it has served me well:

https://bitbucket.org/sqlalchemy/sqlalchemy/src/acbaeb1acb7d...

> Second, you are forced to say explicitly which attributes are modifiable. To draw from the 'person' example, `name` and `age` might be modifiable, but `admin` might be protected. That would be made abundantly clear by `update(person, name=NotSet, age=NotSet)`, but less so, by `update(person, attrs)` or `update(person, kwargs)`.

Whether a field is modifiable is often determined by the current user's access level and the current state of the object. So, putting such restriction at the function definition may have made things too rigid.


> Whether a field is modifiable is often determined by the current user's access level and the current state of the object. So, putting such restriction at the function definition may have made things too rigid.

True, let me try to clarify. There might be some attributes like `admin` that you don't want twiddled via the `update` method but rather mutated via a setter function. In this case, the signature of the `update` function would be helping to indicate that.

(A better example might be the attribute `active` with two methods called `activate` and `deactivate` that send emails and what-not.)


The implementation here is just a suggestion, and trust me, it wasn't much effort ;-)

The aspect that interests me is that this is a problem that crops up occasionally in different Python projects and there doesn't seem to be a recognized best-practice for addressing it.

(The `kwargs` approach seems like the most common but has all the downsides I mentioned.)


That example could probably use some clarification, but the idea is that `name` and `age` in that example are both nullable, so passing in `None` (setting the column to NULL) is different than omitting the value (leaving the column unchanged).


I think this could handled more elegantly if Python supported an Option type, by making 'name' an Option[Option[String]]


Uppercase was chosen to match Python's existing singletons, `True`, `False`, and `None`. Lowercase might look a little too much like a variable, and all-upper might look too much like a module-level const, IMHO.


Agreed. 'Empty' works, as does 'Blank' or 'Unassigned'.'Nil' is concise, but might be a little too easily confused with 'None' (especially so for someone coming from Ruby).

I'd love an approach that used the standard library, but there doesn't seem to be a type-agnostic approach. float('nan') won't make sense for other types, and using `types.NoneType` instead of `None` seems even less understandable.


Fixed, thanks!


Consider applying for YC's Winter 2027 batch! Applications are open till November 2.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: