Let me tell you about my favorite dynamically typed language.
In this language, everything is an object.1
Objects are buckets of properties;2 they’re mappings of names to
These properties can be accessed with dot notation - that is,
bar can be accessed on the object
Not all names that can be accessed with dot notation on an object are actually properties
of that object, but instead might belong to other linked objects.
Objects are linked in this way in a hierarchy for property lookup,
bar doesn’t exist on
foo, whatever object bar “inherits from” will be used
as another bucket of properties to look for that name in, and so on for that object.5
Most objects can have properties tacked on later, using
obj.prop = value
syntax.6 Modifying or creating a new attribute in this way will only effect
the object to the left of the dot, even if using property access on the same
name would have retrieved a property from higher up the inheritance
Functions are a kind of object.
Functions have parameters which specify what names to bind passed arguments
to when executing the body of the function.
Objects are returned from functions with the
return statement, and a default return value is used if no return statement
is encountered while executing the function.
There are no methods as such: no functions which are inherently bound to instances of objects.
Instead the method-ness of a function is determined at runtime.9
When you look up a function on an object and
call it, its behavior is specific to that object.10
Variables are references to objects, and are not constrained in the type of object to which they can refer in any way. The only scope barriers are functions.0 A variable name may refer to a local variable or a variable in a scope surrounding where the function was defined.
In some languages, while inside of a method definition, other methods of the same object can be called without an explicit reference to an object.11 If you want to refer to a method or instance variable from within a function, you need to start with a reference to the object and do property lookup on that; there is no implicit object scope.
If a variable is declared in a function, that name has been declared local for the whole function, even for uses of the name occurring before the declaration of the variable.12 If a variable from an outside scope can be accessed, it can be reassigned.13
Thanks for reading
- or the same object [return]
foo['bar'], to do the same thing. In Python, this notation is used to access an entirely separate namespace - this allows the keys of a dictionary to be entirely separate from its methods, so something like
foo.hasOwnProperty(bar)isn’t necessary when iterating over an objects properties.
Python has classes, which means that non-class objects aren’t allowed to be in the hierarchy of objects that attributes are looked up on. The attribute lookup process is complicated in Python (this document is a great resource), but it’s basically to look for the attribute on the object, then the objects’s class object, then the class objects that class inherits from.
.prototypeproperty of the function that constructed the object via the
__slots__instead of dictionaries, so can’t have arbitrary attributes added.
- This isn’t true of data descriptors in Python - in this case properties apparently later in the property lookup chain can steal a property lookup even when the earlier object has an attribute with that name - this is because the real property lookup chain is more complicated. [return]
foo.bar(), but not
a = foo.bar; a(), which does work in Python)
thisnow refers to the object.
varkeyword. In Python, variables are declared by doing assignment (
a = 2) or use of the
In Python, this means not using the equals sign to declare the name as local, which how you reassign variables - so you’re in a tricky situation. You can use[return]
nonlocal(Python 3 only) in a scope to specify that even though you’re using assignment, that name refers to the variable with the same name in another scope.