A Type for sys.implementation
● Python implementation specifics: PEP 421
Slide 18
Slide 18 text
A Type for sys.implementation
● Python implementation specifics: PEP 421
● the type must communicate the nature of the
namespace
Slide 19
Slide 19 text
A Type for sys.implementation
● Python implementation specifics: PEP 421
● the type must communicate the nature of the
namespace
● dict too soft
Slide 20
Slide 20 text
A Type for sys.implementation
● Python implementation specifics: PEP 421
● the type must communicate the nature of the
namespace
● dict too soft
● namedtuple too hard
Slide 21
Slide 21 text
A Type for sys.implementation
● Python implementation specifics: PEP 421
● the type must communicate the nature of the
namespace
● dict too soft
● namedtuple too hard
● object just right...
Slide 22
Slide 22 text
A Type for sys.implementation
● Python implementation specifics: PEP 421
● the type must communicate the nature of the
namespace
● dict too soft
● namedtuple too hard
● object just right...
● types.SimpleNamespace
Slide 23
Slide 23 text
Communicate the nature of your namespace!
mapping-based
VOLATILE
attribute-based
STABLE
property-based
STATIC
Slide 24
Slide 24 text
Mapping-based
Namespaces
Slide 25
Slide 25 text
mapping-based containers
(volatile namespaces)
● a raw key is mapped to a value
Slide 26
Slide 26 text
Important Mappings:
● obj.__dict__
● execution locals, globals, and builtins
● sys.modules
● os.environ
Slide 27
Slide 27 text
Syntax:
obj[key]
obj[key] = value
del obj[key]
key in obj
Slide 28
Slide 28 text
Some available types:
● dict
● collections.defaultdict
● collections.OrderedDict
● configparser.ConfigParser
● shelve.Shelf
● types.MappingProxyType
● weakref.WeakKeyDictionary
● weakref.WeakValueDictionary
Slide 29
Slide 29 text
How they work:
obj[key]
obj[key] = value
del obj[key]
key in obj
obj.__getitem__(key)
obj.__setitem__(key, val)
obj.__delitem__(key)
obj.__contains__(key)
Slide 30
Slide 30 text
How they work:
obj[key]
obj[key] = value
del obj[key]
key in obj
collections.abc.(Mutable)Mapping
obj.__getitem__(key)
obj.__setitem__(key, val)
obj.__delitem__(key)
obj.__contains__(key)
property-based containers
(static namespaces)
● a proper name aliases an underlying key
● the key is associated with a value
● the names and values are fixed in place
(i.e. read-only)
Some available types:
● collections.namedtuple
● structseq (in C)
Slide 37
Slide 37 text
namedtuple: context + names
Spam = namedtuple('Spam', "a b c")
class Spam(tuple):
def __new__(cls, a, b, c):
return super().__new__(cls, a, b, c)
@property
def a(self):
return self[0]
...
attribute-based containers
(stable namespaces)
● a proper name is associated with a value
Slide 41
Slide 41 text
How they work:
obj.name
obj.name = value
del obj.name
obj.__getattribute__(name)
obj.__setattr__(name, val)
obj.__delattr__(name)
Slide 42
Slide 42 text
How they work:
obj.name
obj.name = value
del obj.name
obj.__getattribute__(name)
obj.__setattr__(name, val)
obj.__delattr__(name)
Slide 43
Slide 43 text
How __getattribute__() works:
1. use a "data" descriptor, if there is one
2. pull from the instance, if it has __dict__
3. use a "non-data" descriptor, if there is one
4. use __getattr__(), if there is one
5. raise AttributeError
How __getattribute__() works:
1. use a "data" descriptor, if there is one
2. pull from the instance, if it has __dict__
3. use a "non-data" descriptor, if there is one
4. use __getattr__(), if there is one
5. raise AttributeError
Slide 49
Slide 49 text
How __getattribute__() works:
1. use a "data" descriptor, if there is one
2. pull from the instance, if it has __dict__
3. use a "non-data" descriptor, if there is one
4. use __getattr__(), if there is one
5. raise AttributeError
MRO!
Slide 50
Slide 50 text
How __getattribute__() works:
1. use a "data" descriptor, if there is one
2. pull from the instance, if it has __dict__
3. use a "non-data" descriptor, if there is one
4. use __getattr__(), if there is one
5. raise AttributeError
Method Resolution Order!
Some available types:
● object
● types.SimpleNamespace
● argparse.Namespace
● multiprocessing.Manager.Namespace
● xmlrpc.client.ServerProxy
● unittest.Mock
Slide 53
Slide 53 text
Gems:
● __qualname__
● operator.attrgetter()
Slide 54
Slide 54 text
Communicate the nature of your namespace!
mapping-based
VOLATILE
attribute-based
STABLE
property-based
STATIC
Slide 55
Slide 55 text
Objects
Slide 56
Slide 56 text
Objects
● are namespace containers
● have namespaces (mostly)
● ergo, as container, proxies a namespace
Slide 57
Slide 57 text
Objects
● are namespace containers
● have namespaces (mostly)
● ergo, as container, proxies a namespace
>>> ns = SimpleNamespace()
>>> ns_ns = vars(ns)
>>> ns.__dict__ is ns_ns
True
Slide 58
Slide 58 text
Objects
● are namespace containers
● have namespaces (mostly)
● ergo, as container, proxies a namespace
● base object type has slots
● assignment/definition: "bind" object to
namespace
__dict__
● most builtins don't have one
● key exception: function objects
Slide 61
Slide 61 text
__dict__
● most builtins don't have one
● key exception: function objects
● module namespaces exposed as __dict__
Slide 62
Slide 62 text
__dict__
● most builtins don't have one
● key exception: function objects
● module namespaces exposed as __dict__
● read-only proxy of class namespaces
exposed as __dict__
● use metaclass __prepare__() to customize
the namespace used during class definition
Slide 63
Slide 63 text
__dict__ vs. __slots__
● slots are turned into descriptors
● __dict__ is disabled
Slide 64
Slide 64 text
Execution
Slide 65
Slide 65 text
Name lookup:
● explicit lookup happens relative to containers
● Method Resolution Order (MRO)
● lookup on class vs. on objects
● special method lookup
Slide 66
Slide 66 text
Name lookup:
● explicit lookup happens relative to containers
● Method Resolution Order (MRO)
● lookup on class vs. on objects
● special method lookup
● implicit lookup happens relative to execution
namespaces...
sys.modules
>>> import mordor
Traceback (most recent call last):
File ".../mordor.py", line 14, in
raise ImportError(boromir_says)
ImportError: One does not simply import Mordor.