That looks the same, but conceptually (and actually, code-wise), that's not what JS is doing. Here's what's actually happening, in psudo-python:
class Person({name:"bill", addr:"foo"}):
#there's no syntax for object literals in Python
#such a thing doesn't even make sense: so I'm improvising.
pass
charlie = Person()
charlie.name = "charlie"
charlie.addr = "baz"
class NewPerson(charlie):
#note charlie is an object, not a class
pass
bill = NewPerson()
In JS, charlie isn't a class, charlie is an object: you can change all its properties and everything, just like any other object. It's not a class, because there aren't any.
Classless object literals actually don't make sense in the Python model. It seems like you're the one who needs to brush up.
In any case you're not actually providing any links or facts, so unless I dig through long articles on metaclasses in python, I can't verify anything you say. Please prove your point, or at least provide I link so I can verify.
> In JS, charlie isn't a class, charlie is an object: you can change all its properties and everything, just like any other object. It's not a class, because there aren't any.
Right; this is actually why I like Python's way a bit better: it makes a more formal distinction between the two. In Python, Charlie is also an object, and you can change all its properties and everything, just like most¹ other objects.
Most of what you try to use to distinguish JS from Python applies just as well to Python. No, it isn't exactly the same, and I think the semantically equivalent code in Python will often contain more information than the JS. E.g., in my conversion of your JS, the class is an instance of `type`, whereas — as you correctly note — it's "just" an object in JS. It's not really though; in most JS that devs will write, the object is a type, but that distinction isn't explicit in the code. It's implicit in the dev's intentions, expressed only in the general sense that the code is being used.
e.g., if I saw, in JS,
var Person = function(){};
Person.prototype = {name:"bill", addr:"foo"};
var charlie = new Person();
while it is true, technically, that `Person` is a function and `Person.prototype` is an object, the semantic meaning being expressed in this manner by the author of this setup is that `Person` is a type, and that charlie is an instance of that type. It's just explicit in Python. (To some degree, JS is aware of this fact too; `charlie instanceof Person` is `true`, after all.)
In a single-inheritance class in Python, during attribute lookup, Python will attempt to look the attribute up on the object's __dict__; if it doesn't exist, then it looks up the parent type (by looking at __class__) and then recurses, trying to look the attribute up there, and proceeding up the "chain".²
In JS, during attribute lookup, JS will attempt to look the attribute up on the object's internal list of attribute (I don't believe this is exposed like __dict__ in Python); if it doesn't exist, then it looks up the parent type (by looking at __proto__) and then recurses, trying to look the attribute up there, and proceeding up the "chain".
What material difference exists here?
¹objects in Python can forbid attributes from being set, or limit the available attributes. I'm not sure to what extend JS lets you do that. e.g., `object` in Python is very restrictive about allowing additional objects.
²I'm explicitly ignoring multiple inheritance here, so I'm vastly simplifying. Python will actually use the MRO for this procedure, but in the case of simple inheritance, that's equivalent to following __class__. I'm also ignoring __slots__ for simplicity.