A namespace is a dictionary, mapping names (as strings) to values. When you do an assignment, like a = 1
, you're mutating a namespace. When you make a reference, like print(a)
, Python looks through a list of namespaces to try and find one with the name as a key.
A scope defines which namespaces will be looked in and in what order. The scope of any reference always starts in the local namespace, and moves outwards until it reaches the module's global namespace, before moving on to the builtins
(the namespace that references Python's predefined functions and constants, like range
and getattr
), which is the end of the line.
Imagine you have a function named inner
, nested within a global function named outer
, and inner
contains a reference to a name. Python first looks in the inner
namespace. If the name's not there, Python then looks in the outer
namespace. If that fails, Python tries the module's global
namespace, then the builtin
namespace, eventually throwing a NameError
if the name isn't found.
When we say x
is in a function's namespace, we mean it is defined there, locally within the function. When we say x
is in the function's scope, we mean x
is either in the function's namespace or in any of the outer namespaces that the function's namespace is currently nested within.
Whenever you define a function, you create a new namespace and a new scope. The namespace is the new, local hash of names. The scope is the implied chain of namespaces that starts at the new namespace, then works its way through any outer namespaces (outer scopes), up to the global namespace (the global scope), and on to the builtins.
The terms can be used almost interchangeably, but that's not because they mean the same thing; it's because they overlap a lot in what they imply.
One difference: In Python, you can define a subclass MySubclass
of MyClass
, and then you can freely add objects of MyClass
with objects of MySubclass
.
Haskell tends to avoid subtyping: if you have a typeclass Addable
with a function add :: Addable a => a -> a -> a
, both summands must always be of the same type. It can be any type that is an instance of Addable
, but it must be the same for both summands and the result.
Another difference: in Haskell you can "retroactively" make a type an instance of a typeclass. For example you can create a typeclass and declare instances for some preexisting types that fit the mold. In Python, when you define a class you must list what classes it will extend.
Yet another difference: in Python, "method dispatch" (what method implementation is actually executed in an invocation) is determined by the object receiving the invocation. Haskell typeclasses allow dispatching on the expected return type of a function. A clasic example is the function read :: Read a => String -> a
. Depending on the desired type a
of the result, different reading functions will be called.
This a good talk on Haskell typeclasses which, from minute 40 onwards, compares them to OO interfaces.
Best Answer
A proxy has no other functionality than to forward actions. A class that delegates also adds its own functionality.
In that, effectively, a proxy is a special case of delegation.
As @Jules said, your example is one of a proxy.