The inconsistencies you mention are (in a well written code base) very rare. If you call a method get_name() odds are you are going to get back a string. If you seem to randomly get back an int or a dictionary or a datetime object it's a pretty good sign the code is foobar'd. Good Python programmers don't abuse the dynamic nature of the language. Methods should return predictable types (documentation is important), it might return different types depending on the input but this should be documented and obvious (say a parse date method that returns a datatime object if you pass it a string containing a date and time). The values() example you use is very clearly documented as returning a ValuesQuerySet that supplies dictionaries not models (http://docs.djangoproject.com/en/dev/ref/models/querysets/#v...).
In a number of years using python, the standard library and 3rd party libraries I've never been left wondering "If I pass X to this method what the hell type am I going to get back". Just like in C/C++ I need to remember it returns a list or a string or a dictionary but that's usually where the mental overhead stops.
Python is dynamic which means it's flexible. Flexibility is usually reached by sacrificing simplicity so Python encourages testing and good documentation. I would argue that these are both necessary features of any good code base, Python is just more upfront about this than a number of languages.