Boxes are seductive, easy to think about, and horribly wrong. Every buffer overrun, and almost every other security hole in modern software, can be traced to a box that someone thought would be big enough---but wasn't.
In Python, you don't put things in boxes. Python represents your view on reality, and while you can virtually categorize things, it involves no physical moving (or, even worse, copying) of objects. Objects stay where they are; you just name them according to some scheme. They don't even know (nor care) whether they are named.
The beauty of Python is that the same philosophy works both up (namespaces, which map names to objects, are just ordinary objects, usually of type dict) and down (object's attributes are not contained inside it---they are just named from it, and they live separately).
So, names are just some objects (usually of type str) you associate with objects using some other objects (namespaces). Objects are obviously not created by names, they are created by evaluating literals. Every time  is evaluated (possibly with something in between), a new list is made. So, evaluating [*5]*7 makes two lists, an inner one and an outer one. Of course then outer is the same list as outer---what other list is there?
Of course, Python is allowed to cheat in the name of performance, as long as you don't notice the sleight of hand. Many objects constructed by literals are immutable, so Python doesn't have to construct a brand new number eight every time you write 8 in your code (and Python executes it)---it just gives you some number eight it has already constructed; you won't see any operational difference since there is no way you could change its value. (Of course, you can see a difference through is keyword, or id builtin, but that's just using the wrong tool---see Pass by what? for the crucial difference in philosophies in treating objects and values.)
Closely related to variables is the notion of changing things (after all, it's the etymology of the term "variable").
“change” has two meanings, which are different in Python. Let’s call them “replace” and “modify” (Python terminology is “rebind” and “mutate”, but here I think it can be profitable to depart from standard terminology.) Usually, when people are confused about variables, it's because they mixed up those two different meanings---using one instead of another, or thinking they are the same when they aren't.
As I said above, every rebinding is a mutation, but not of the same object. Rebinding of a name x is mutation of whatever namespace contains x. Also, up to some details at the bottom (you have to start somewhere) every mutation of an object is a rebinding of an object, but a different object. Mutation of x is a rebinding of some attribute (or component) of x.
In our new terminology, when you replace an object, you let it be, you just put something else in its place - or rather, use its name for something else. When you replace your car, your old car still continues to exist (unless it's garbage collected), but you just start calling some other car my_car.
a=1 means a is a name for an object 1. b=a means b is another name for the same object. b=3 means b is now no longer a name for that object, but for another object, 3. a is of course still the name for the same object - you haven’t changed a by replacing b.
On the other hand, when you modify an object, it is still the same object - you just changed (replaced, or possibly modified) some attribute or component of it. When you paint your car blue, it is still the same car, but my_car.color is now #00f instead of whatever it was before.
a=[1,2,3,4] means a is a name for an object, some concrete list that currently has four elements. b=a means b is a name for the same object. b=7 replaces first component of b, modifying b, but it doesn't replace b: it’s still the same object. So a is the first component of that same object, that is, 7.