My first impression is that this isn't a problem in need of solving; it just needs a change in approach.
The first is the conflation of classes and functions that work with classes. The update function in the example isn't reusable at all, implies you can update something other than a Person, and 'NotSet' doesn't fix that. So have it as a method on Person, and pass in a list of attributes to change as opposed to enumerating each field as a named parameter. You have the fields on the class for more fine-grained control, and functions like this don't necessarily make the code clearer.
Given that, I don't think the example presents a valid use-case for implementing 'NotSet' or whatever you want to call it. The problem is in the implementation, not Python, and the solution is a hack to enable you to continue with this approach.
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.
The first is the conflation of classes and functions that work with classes. The update function in the example isn't reusable at all, implies you can update something other than a Person, and 'NotSet' doesn't fix that. So have it as a method on Person, and pass in a list of attributes to change as opposed to enumerating each field as a named parameter. You have the fields on the class for more fine-grained control, and functions like this don't necessarily make the code clearer.
Given that, I don't think the example presents a valid use-case for implementing 'NotSet' or whatever you want to call it. The problem is in the implementation, not Python, and the solution is a hack to enable you to continue with this approach.