Yes, the dictionary size will change when you remove keys, in that the outward length changes.  This means that an exception will be thrown when looping over a dictionary while deleting keys inside the loop.
Yes, a sentinel value (named dummy) is used to replace the deleted key, so that hash collision tests for still existing values still find the existing values.
However, the table is not rebuilt; rebuilding is only done for insertions. Yes, this means that a large dictionary table will keep using some memory after a lot of deletions from it; you can force a resize by replacing the dictionary with a copy, or by inserting new values until the table is 2/3rds full (at which point a resize can end up shrinking the table).
If you are curious, and understand C well enough, take a look at the C implementation for all the (well documented) details. You could also watch this Pycon 2010 presentation by Brandon Rhodes about how CPython dict works, or pick up a copy of Beautiful Code, which includes a chapter on the implementation written by Andrew Kuchling.