If you think through what these commands actually do, it's pretty simple.
a.py:
import b
foo = 0
b.py:
bar = 1
c.py:
import a
From c, you can't just say foo, you have to say a.foo. The same is true for every name in a—constants, variables, functions, classes, and even modules. And that includes b.
So, you can't say bar or a.bar, but you can say a.b.bar.
Now, what if you change it like this:
a.py:
from b import *
foo = 0
b.py:
bar = 1
c.py:
from a import *
What that from b import * does is take everything in b's namespace, and puts it into a's namespace, so you can directly say bar from within a. And then, when you do from a import *, that takes everything in a's namespace, and puts it into c's, so just as you can do foo, you can also do bar.
This is why you usually don't want to do from b import * anywhere except in your top-level script—because your namespaces get all merged together.
It's also why you can restrict what gets picked up by * with __all__:
a.py:
from b import *
__all__ = ['foo']
foo = 0
b.py:
bar = 1
c.py:
from a import *
Now, from c, you can do c.foo, but not c.bar.
So, a can do from b import * to implement its own features, without exposing all of b's internals to its users.