Methods like datastore.key.Key.dataset act as both setters and getters and return a different type of object depending on whether they set or get.
In this case key.dataset(dataset=NEW_DATASET) returns a new clone Key object (to keep the instances immutable, as @tseaver pointed out was discussed in #3) where key.dataset() simply returns a datastore.dataset.Dataset object.
For me (@dhermes) it's really a method which is somewhat overloaded in it's scope (though I'll acknowledge the code is typically short).
I'd be much more in favor of two separate methods for getting and setting, i.e.
update_dataset as a method and dataset decorated with @property as a getter only.
curr_dataset = key.dataset # Actually a getter.
new_key = key.update_dataset(dataset=NEW_DATASET)