| Georg Brandl | 45cceeb | 2010-05-19 21:39:51 +0000 | [diff] [blame] | 1 | ====================== | 
 | 2 | Descriptor HowTo Guide | 
 | 3 | ====================== | 
 | 4 |  | 
 | 5 | :Author: Raymond Hettinger | 
 | 6 | :Contact: <python at rcn dot com> | 
 | 7 |  | 
 | 8 | .. Contents:: | 
 | 9 |  | 
 | 10 | Abstract | 
 | 11 | -------- | 
 | 12 |  | 
 | 13 | Defines descriptors, summarizes the protocol, and shows how descriptors are | 
 | 14 | called.  Examines a custom descriptor and several built-in python descriptors | 
 | 15 | including functions, properties, static methods, and class methods.  Shows how | 
 | 16 | each works by giving a pure Python equivalent and a sample application. | 
 | 17 |  | 
 | 18 | Learning about descriptors not only provides access to a larger toolset, it | 
 | 19 | creates a deeper understanding of how Python works and an appreciation for the | 
 | 20 | elegance of its design. | 
 | 21 |  | 
 | 22 |  | 
 | 23 | Definition and Introduction | 
 | 24 | --------------------------- | 
 | 25 |  | 
 | 26 | In general, a descriptor is an object attribute with "binding behavior", one | 
 | 27 | whose attribute access has been overridden by methods in the descriptor | 
 | 28 | protocol.  Those methods are :meth:`__get__`, :meth:`__set__`, and | 
 | 29 | :meth:`__delete__`.  If any of those methods are defined for an object, it is | 
 | 30 | said to be a descriptor. | 
 | 31 |  | 
 | 32 | The default behavior for attribute access is to get, set, or delete the | 
 | 33 | attribute from an object's dictionary.  For instance, ``a.x`` has a lookup chain | 
 | 34 | starting with ``a.__dict__['x']``, then ``type(a).__dict__['x']``, and | 
 | 35 | continuing through the base classes of ``type(a)`` excluding metaclasses. If the | 
 | 36 | looked-up value is an object defining one of the descriptor methods, then Python | 
 | 37 | may override the default behavior and invoke the descriptor method instead. | 
 | 38 | Where this occurs in the precedence chain depends on which descriptor methods | 
| Florent Xicluna | aa6c1d2 | 2011-12-12 18:54:29 +0100 | [diff] [blame] | 39 | were defined. | 
| Georg Brandl | 45cceeb | 2010-05-19 21:39:51 +0000 | [diff] [blame] | 40 |  | 
 | 41 | Descriptors are a powerful, general purpose protocol.  They are the mechanism | 
 | 42 | behind properties, methods, static methods, class methods, and :func:`super()`. | 
| Ezio Melotti | 222e61e | 2011-07-31 22:49:18 +0300 | [diff] [blame] | 43 | They are used throughout Python itself to implement the new style classes | 
| Georg Brandl | 45cceeb | 2010-05-19 21:39:51 +0000 | [diff] [blame] | 44 | introduced in version 2.2.  Descriptors simplify the underlying C-code and offer | 
 | 45 | a flexible set of new tools for everyday Python programs. | 
 | 46 |  | 
 | 47 |  | 
 | 48 | Descriptor Protocol | 
 | 49 | ------------------- | 
 | 50 |  | 
 | 51 | ``descr.__get__(self, obj, type=None) --> value`` | 
 | 52 |  | 
 | 53 | ``descr.__set__(self, obj, value) --> None`` | 
 | 54 |  | 
 | 55 | ``descr.__delete__(self, obj) --> None`` | 
 | 56 |  | 
 | 57 | That is all there is to it.  Define any of these methods and an object is | 
 | 58 | considered a descriptor and can override default behavior upon being looked up | 
 | 59 | as an attribute. | 
 | 60 |  | 
 | 61 | If an object defines both :meth:`__get__` and :meth:`__set__`, it is considered | 
 | 62 | a data descriptor.  Descriptors that only define :meth:`__get__` are called | 
 | 63 | non-data descriptors (they are typically used for methods but other uses are | 
 | 64 | possible). | 
 | 65 |  | 
 | 66 | Data and non-data descriptors differ in how overrides are calculated with | 
 | 67 | respect to entries in an instance's dictionary.  If an instance's dictionary | 
 | 68 | has an entry with the same name as a data descriptor, the data descriptor | 
 | 69 | takes precedence.  If an instance's dictionary has an entry with the same | 
 | 70 | name as a non-data descriptor, the dictionary entry takes precedence. | 
 | 71 |  | 
 | 72 | To make a read-only data descriptor, define both :meth:`__get__` and | 
 | 73 | :meth:`__set__` with the :meth:`__set__` raising an :exc:`AttributeError` when | 
 | 74 | called.  Defining the :meth:`__set__` method with an exception raising | 
 | 75 | placeholder is enough to make it a data descriptor. | 
 | 76 |  | 
 | 77 |  | 
 | 78 | Invoking Descriptors | 
 | 79 | -------------------- | 
 | 80 |  | 
 | 81 | A descriptor can be called directly by its method name.  For example, | 
 | 82 | ``d.__get__(obj)``. | 
 | 83 |  | 
 | 84 | Alternatively, it is more common for a descriptor to be invoked automatically | 
 | 85 | upon attribute access.  For example, ``obj.d`` looks up ``d`` in the dictionary | 
 | 86 | of ``obj``.  If ``d`` defines the method :meth:`__get__`, then ``d.__get__(obj)`` | 
 | 87 | is invoked according to the precedence rules listed below. | 
 | 88 |  | 
 | 89 | The details of invocation depend on whether ``obj`` is an object or a class. | 
| Georg Brandl | 45cceeb | 2010-05-19 21:39:51 +0000 | [diff] [blame] | 90 |  | 
 | 91 | For objects, the machinery is in :meth:`object.__getattribute__` which | 
 | 92 | transforms ``b.x`` into ``type(b).__dict__['x'].__get__(b, type(b))``.  The | 
 | 93 | implementation works through a precedence chain that gives data descriptors | 
 | 94 | priority over instance variables, instance variables priority over non-data | 
| Benjamin Peterson | 57fb11b | 2014-10-06 21:10:25 -0400 | [diff] [blame] | 95 | descriptors, and assigns lowest priority to :meth:`__getattr__` if provided. | 
 | 96 | The full C implementation can be found in :c:func:`PyObject_GenericGetAttr()` in | 
 | 97 | :source:`Objects/object.c`. | 
| Georg Brandl | 45cceeb | 2010-05-19 21:39:51 +0000 | [diff] [blame] | 98 |  | 
 | 99 | For classes, the machinery is in :meth:`type.__getattribute__` which transforms | 
 | 100 | ``B.x`` into ``B.__dict__['x'].__get__(None, B)``.  In pure Python, it looks | 
 | 101 | like:: | 
 | 102 |  | 
 | 103 |     def __getattribute__(self, key): | 
 | 104 |         "Emulate type_getattro() in Objects/typeobject.c" | 
 | 105 |         v = object.__getattribute__(self, key) | 
 | 106 |         if hasattr(v, '__get__'): | 
 | 107 |            return v.__get__(None, self) | 
 | 108 |         return v | 
 | 109 |  | 
 | 110 | The important points to remember are: | 
 | 111 |  | 
 | 112 | * descriptors are invoked by the :meth:`__getattribute__` method | 
 | 113 | * overriding :meth:`__getattribute__` prevents automatic descriptor calls | 
| Georg Brandl | 45cceeb | 2010-05-19 21:39:51 +0000 | [diff] [blame] | 114 | * :meth:`object.__getattribute__` and :meth:`type.__getattribute__` make | 
 | 115 |   different calls to :meth:`__get__`. | 
 | 116 | * data descriptors always override instance dictionaries. | 
 | 117 | * non-data descriptors may be overridden by instance dictionaries. | 
 | 118 |  | 
 | 119 | The object returned by ``super()`` also has a custom :meth:`__getattribute__` | 
 | 120 | method for invoking descriptors.  The call ``super(B, obj).m()`` searches | 
 | 121 | ``obj.__class__.__mro__`` for the base class ``A`` immediately following ``B`` | 
| Benjamin Peterson | 910a665 | 2013-10-18 12:57:55 -0400 | [diff] [blame] | 122 | and then returns ``A.__dict__['m'].__get__(obj, B)``.  If not a descriptor, | 
| Georg Brandl | 45cceeb | 2010-05-19 21:39:51 +0000 | [diff] [blame] | 123 | ``m`` is returned unchanged.  If not in the dictionary, ``m`` reverts to a | 
 | 124 | search using :meth:`object.__getattribute__`. | 
 | 125 |  | 
| Florent Xicluna | aa6c1d2 | 2011-12-12 18:54:29 +0100 | [diff] [blame] | 126 | The implementation details are in :c:func:`super_getattro()` in | 
| Benjamin Peterson | 57fb11b | 2014-10-06 21:10:25 -0400 | [diff] [blame] | 127 | :source:`Objects/typeobject.c`.  and a pure Python equivalent can be found in | 
 | 128 | `Guido's Tutorial`_. | 
| Georg Brandl | 45cceeb | 2010-05-19 21:39:51 +0000 | [diff] [blame] | 129 |  | 
| Georg Brandl | 9bdcb3b | 2014-10-29 09:37:43 +0100 | [diff] [blame] | 130 | .. _`Guido's Tutorial`: https://www.python.org/download/releases/2.2.3/descrintro/#cooperation | 
| Georg Brandl | 45cceeb | 2010-05-19 21:39:51 +0000 | [diff] [blame] | 131 |  | 
 | 132 | The details above show that the mechanism for descriptors is embedded in the | 
 | 133 | :meth:`__getattribute__()` methods for :class:`object`, :class:`type`, and | 
 | 134 | :func:`super`.  Classes inherit this machinery when they derive from | 
 | 135 | :class:`object` or if they have a meta-class providing similar functionality. | 
 | 136 | Likewise, classes can turn-off descriptor invocation by overriding | 
 | 137 | :meth:`__getattribute__()`. | 
 | 138 |  | 
 | 139 |  | 
 | 140 | Descriptor Example | 
 | 141 | ------------------ | 
 | 142 |  | 
 | 143 | The following code creates a class whose objects are data descriptors which | 
 | 144 | print a message for each get or set.  Overriding :meth:`__getattribute__` is | 
 | 145 | alternate approach that could do this for every attribute.  However, this | 
 | 146 | descriptor is useful for monitoring just a few chosen attributes:: | 
 | 147 |  | 
 | 148 |     class RevealAccess(object): | 
 | 149 |         """A data descriptor that sets and returns values | 
 | 150 |            normally and prints a message logging their access. | 
 | 151 |         """ | 
 | 152 |  | 
 | 153 |         def __init__(self, initval=None, name='var'): | 
 | 154 |             self.val = initval | 
 | 155 |             self.name = name | 
 | 156 |  | 
 | 157 |         def __get__(self, obj, objtype): | 
 | 158 |             print('Retrieving', self.name) | 
 | 159 |             return self.val | 
 | 160 |  | 
 | 161 |         def __set__(self, obj, val): | 
 | 162 |             print('Updating', self.name) | 
 | 163 |             self.val = val | 
 | 164 |  | 
 | 165 |     >>> class MyClass(object): | 
 | 166 |         x = RevealAccess(10, 'var "x"') | 
 | 167 |         y = 5 | 
 | 168 |  | 
 | 169 |     >>> m = MyClass() | 
 | 170 |     >>> m.x | 
 | 171 |     Retrieving var "x" | 
 | 172 |     10 | 
 | 173 |     >>> m.x = 20 | 
 | 174 |     Updating var "x" | 
 | 175 |     >>> m.x | 
 | 176 |     Retrieving var "x" | 
 | 177 |     20 | 
 | 178 |     >>> m.y | 
 | 179 |     5 | 
 | 180 |  | 
 | 181 | The protocol is simple and offers exciting possibilities.  Several use cases are | 
 | 182 | so common that they have been packaged into individual function calls. | 
 | 183 | Properties, bound and unbound methods, static methods, and class methods are all | 
 | 184 | based on the descriptor protocol. | 
 | 185 |  | 
 | 186 |  | 
 | 187 | Properties | 
 | 188 | ---------- | 
 | 189 |  | 
 | 190 | Calling :func:`property` is a succinct way of building a data descriptor that | 
 | 191 | triggers function calls upon access to an attribute.  Its signature is:: | 
 | 192 |  | 
 | 193 |     property(fget=None, fset=None, fdel=None, doc=None) -> property attribute | 
 | 194 |  | 
 | 195 | The documentation shows a typical use to define a managed attribute ``x``:: | 
 | 196 |  | 
 | 197 |     class C(object): | 
 | 198 |         def getx(self): return self.__x | 
 | 199 |         def setx(self, value): self.__x = value | 
 | 200 |         def delx(self): del self.__x | 
 | 201 |         x = property(getx, setx, delx, "I'm the 'x' property.") | 
 | 202 |  | 
 | 203 | To see how :func:`property` is implemented in terms of the descriptor protocol, | 
 | 204 | here is a pure Python equivalent:: | 
 | 205 |  | 
 | 206 |     class Property(object): | 
 | 207 |         "Emulate PyProperty_Type() in Objects/descrobject.c" | 
 | 208 |  | 
 | 209 |         def __init__(self, fget=None, fset=None, fdel=None, doc=None): | 
 | 210 |             self.fget = fget | 
 | 211 |             self.fset = fset | 
 | 212 |             self.fdel = fdel | 
| Raymond Hettinger | 632c8c8 | 2013-03-10 09:41:18 -0700 | [diff] [blame] | 213 |             if doc is None and fget is not None: | 
 | 214 |                 doc = fget.__doc__ | 
| Georg Brandl | 45cceeb | 2010-05-19 21:39:51 +0000 | [diff] [blame] | 215 |             self.__doc__ = doc | 
 | 216 |  | 
 | 217 |         def __get__(self, obj, objtype=None): | 
 | 218 |             if obj is None: | 
 | 219 |                 return self | 
 | 220 |             if self.fget is None: | 
| Raymond Hettinger | 632c8c8 | 2013-03-10 09:41:18 -0700 | [diff] [blame] | 221 |                 raise AttributeError("unreadable attribute") | 
| Georg Brandl | 45cceeb | 2010-05-19 21:39:51 +0000 | [diff] [blame] | 222 |             return self.fget(obj) | 
 | 223 |  | 
 | 224 |         def __set__(self, obj, value): | 
 | 225 |             if self.fset is None: | 
| Raymond Hettinger | 632c8c8 | 2013-03-10 09:41:18 -0700 | [diff] [blame] | 226 |                 raise AttributeError("can't set attribute") | 
| Georg Brandl | 45cceeb | 2010-05-19 21:39:51 +0000 | [diff] [blame] | 227 |             self.fset(obj, value) | 
 | 228 |  | 
 | 229 |         def __delete__(self, obj): | 
 | 230 |             if self.fdel is None: | 
| Raymond Hettinger | 632c8c8 | 2013-03-10 09:41:18 -0700 | [diff] [blame] | 231 |                 raise AttributeError("can't delete attribute") | 
| Georg Brandl | 45cceeb | 2010-05-19 21:39:51 +0000 | [diff] [blame] | 232 |             self.fdel(obj) | 
 | 233 |  | 
| Raymond Hettinger | 632c8c8 | 2013-03-10 09:41:18 -0700 | [diff] [blame] | 234 |         def getter(self, fget): | 
 | 235 |             return type(self)(fget, self.fset, self.fdel, self.__doc__) | 
 | 236 |  | 
 | 237 |         def setter(self, fset): | 
 | 238 |             return type(self)(self.fget, fset, self.fdel, self.__doc__) | 
 | 239 |  | 
 | 240 |         def deleter(self, fdel): | 
 | 241 |             return type(self)(self.fget, self.fset, fdel, self.__doc__) | 
 | 242 |  | 
| Georg Brandl | 45cceeb | 2010-05-19 21:39:51 +0000 | [diff] [blame] | 243 | The :func:`property` builtin helps whenever a user interface has granted | 
 | 244 | attribute access and then subsequent changes require the intervention of a | 
 | 245 | method. | 
 | 246 |  | 
 | 247 | For instance, a spreadsheet class may grant access to a cell value through | 
 | 248 | ``Cell('b10').value``. Subsequent improvements to the program require the cell | 
 | 249 | to be recalculated on every access; however, the programmer does not want to | 
 | 250 | affect existing client code accessing the attribute directly.  The solution is | 
 | 251 | to wrap access to the value attribute in a property data descriptor:: | 
 | 252 |  | 
 | 253 |     class Cell(object): | 
 | 254 |         . . . | 
 | 255 |         def getvalue(self, obj): | 
 | 256 |             "Recalculate cell before returning value" | 
 | 257 |             self.recalc() | 
 | 258 |             return obj._value | 
 | 259 |         value = property(getvalue) | 
 | 260 |  | 
 | 261 |  | 
 | 262 | Functions and Methods | 
 | 263 | --------------------- | 
 | 264 |  | 
 | 265 | Python's object oriented features are built upon a function based environment. | 
 | 266 | Using non-data descriptors, the two are merged seamlessly. | 
 | 267 |  | 
 | 268 | Class dictionaries store methods as functions.  In a class definition, methods | 
 | 269 | are written using :keyword:`def` and :keyword:`lambda`, the usual tools for | 
 | 270 | creating functions.  The only difference from regular functions is that the | 
 | 271 | first argument is reserved for the object instance.  By Python convention, the | 
 | 272 | instance reference is called *self* but may be called *this* or any other | 
 | 273 | variable name. | 
 | 274 |  | 
 | 275 | To support method calls, functions include the :meth:`__get__` method for | 
 | 276 | binding methods during attribute access.  This means that all functions are | 
 | 277 | non-data descriptors which return bound or unbound methods depending whether | 
 | 278 | they are invoked from an object or a class.  In pure python, it works like | 
 | 279 | this:: | 
 | 280 |  | 
 | 281 |     class Function(object): | 
 | 282 |         . . . | 
 | 283 |         def __get__(self, obj, objtype=None): | 
 | 284 |             "Simulate func_descr_get() in Objects/funcobject.c" | 
 | 285 |             return types.MethodType(self, obj, objtype) | 
 | 286 |  | 
 | 287 | Running the interpreter shows how the function descriptor works in practice:: | 
 | 288 |  | 
 | 289 |     >>> class D(object): | 
 | 290 |          def f(self, x): | 
 | 291 |               return x | 
 | 292 |  | 
 | 293 |     >>> d = D() | 
 | 294 |     >>> D.__dict__['f'] # Stored internally as a function | 
 | 295 |     <function f at 0x00C45070> | 
 | 296 |     >>> D.f             # Get from a class becomes an unbound method | 
 | 297 |     <unbound method D.f> | 
 | 298 |     >>> d.f             # Get from an instance becomes a bound method | 
 | 299 |     <bound method D.f of <__main__.D object at 0x00B18C90>> | 
 | 300 |  | 
 | 301 | The output suggests that bound and unbound methods are two different types. | 
| Georg Brandl | 6faee4e | 2010-09-21 14:48:28 +0000 | [diff] [blame] | 302 | While they could have been implemented that way, the actual C implementation of | 
| Benjamin Peterson | 57fb11b | 2014-10-06 21:10:25 -0400 | [diff] [blame] | 303 | :c:type:`PyMethod_Type` in :source:`Objects/classobject.c` is a single object | 
 | 304 | with two different representations depending on whether the :attr:`im_self` | 
 | 305 | field is set or is *NULL* (the C equivalent of *None*). | 
| Georg Brandl | 45cceeb | 2010-05-19 21:39:51 +0000 | [diff] [blame] | 306 |  | 
 | 307 | Likewise, the effects of calling a method object depend on the :attr:`im_self` | 
 | 308 | field. If set (meaning bound), the original function (stored in the | 
 | 309 | :attr:`im_func` field) is called as expected with the first argument set to the | 
 | 310 | instance.  If unbound, all of the arguments are passed unchanged to the original | 
 | 311 | function. The actual C implementation of :func:`instancemethod_call()` is only | 
 | 312 | slightly more complex in that it includes some type checking. | 
 | 313 |  | 
 | 314 |  | 
 | 315 | Static Methods and Class Methods | 
 | 316 | -------------------------------- | 
 | 317 |  | 
 | 318 | Non-data descriptors provide a simple mechanism for variations on the usual | 
 | 319 | patterns of binding functions into methods. | 
 | 320 |  | 
 | 321 | To recap, functions have a :meth:`__get__` method so that they can be converted | 
 | 322 | to a method when accessed as attributes.  The non-data descriptor transforms a | 
 | 323 | ``obj.f(*args)`` call into ``f(obj, *args)``.  Calling ``klass.f(*args)`` | 
 | 324 | becomes ``f(*args)``. | 
 | 325 |  | 
 | 326 | This chart summarizes the binding and its two most useful variants: | 
 | 327 |  | 
 | 328 |       +-----------------+----------------------+------------------+ | 
 | 329 |       | Transformation  | Called from an       | Called from a    | | 
 | 330 |       |                 | Object               | Class            | | 
 | 331 |       +=================+======================+==================+ | 
 | 332 |       | function        | f(obj, \*args)       | f(\*args)        | | 
 | 333 |       +-----------------+----------------------+------------------+ | 
 | 334 |       | staticmethod    | f(\*args)            | f(\*args)        | | 
 | 335 |       +-----------------+----------------------+------------------+ | 
 | 336 |       | classmethod     | f(type(obj), \*args) | f(klass, \*args) | | 
 | 337 |       +-----------------+----------------------+------------------+ | 
 | 338 |  | 
 | 339 | Static methods return the underlying function without changes.  Calling either | 
 | 340 | ``c.f`` or ``C.f`` is the equivalent of a direct lookup into | 
 | 341 | ``object.__getattribute__(c, "f")`` or ``object.__getattribute__(C, "f")``. As a | 
 | 342 | result, the function becomes identically accessible from either an object or a | 
 | 343 | class. | 
 | 344 |  | 
 | 345 | Good candidates for static methods are methods that do not reference the | 
 | 346 | ``self`` variable. | 
 | 347 |  | 
 | 348 | For instance, a statistics package may include a container class for | 
 | 349 | experimental data.  The class provides normal methods for computing the average, | 
 | 350 | mean, median, and other descriptive statistics that depend on the data. However, | 
 | 351 | there may be useful functions which are conceptually related but do not depend | 
 | 352 | on the data.  For instance, ``erf(x)`` is handy conversion routine that comes up | 
 | 353 | in statistical work but does not directly depend on a particular dataset. | 
 | 354 | It can be called either from an object or the class:  ``s.erf(1.5) --> .9332`` or | 
 | 355 | ``Sample.erf(1.5) --> .9332``. | 
 | 356 |  | 
 | 357 | Since staticmethods return the underlying function with no changes, the example | 
 | 358 | calls are unexciting:: | 
 | 359 |  | 
 | 360 |     >>> class E(object): | 
 | 361 |          def f(x): | 
 | 362 |               print(x) | 
 | 363 |          f = staticmethod(f) | 
 | 364 |  | 
 | 365 |     >>> print(E.f(3)) | 
 | 366 |     3 | 
 | 367 |     >>> print(E().f(3)) | 
 | 368 |     3 | 
 | 369 |  | 
 | 370 | Using the non-data descriptor protocol, a pure Python version of | 
 | 371 | :func:`staticmethod` would look like this:: | 
 | 372 |  | 
 | 373 |     class StaticMethod(object): | 
 | 374 |      "Emulate PyStaticMethod_Type() in Objects/funcobject.c" | 
 | 375 |  | 
 | 376 |      def __init__(self, f): | 
 | 377 |           self.f = f | 
 | 378 |  | 
 | 379 |      def __get__(self, obj, objtype=None): | 
 | 380 |           return self.f | 
 | 381 |  | 
 | 382 | Unlike static methods, class methods prepend the class reference to the | 
 | 383 | argument list before calling the function.  This format is the same | 
 | 384 | for whether the caller is an object or a class:: | 
 | 385 |  | 
 | 386 |     >>> class E(object): | 
 | 387 |          def f(klass, x): | 
 | 388 |               return klass.__name__, x | 
 | 389 |          f = classmethod(f) | 
 | 390 |  | 
 | 391 |     >>> print(E.f(3)) | 
 | 392 |     ('E', 3) | 
 | 393 |     >>> print(E().f(3)) | 
 | 394 |     ('E', 3) | 
 | 395 |  | 
 | 396 |  | 
 | 397 | This behavior is useful whenever the function only needs to have a class | 
 | 398 | reference and does not care about any underlying data.  One use for classmethods | 
 | 399 | is to create alternate class constructors.  In Python 2.3, the classmethod | 
 | 400 | :func:`dict.fromkeys` creates a new dictionary from a list of keys.  The pure | 
 | 401 | Python equivalent is:: | 
 | 402 |  | 
| Raymond Hettinger | 686aae4 | 2013-03-10 09:50:37 -0700 | [diff] [blame] | 403 |     class Dict(object): | 
| Georg Brandl | 45cceeb | 2010-05-19 21:39:51 +0000 | [diff] [blame] | 404 |         . . . | 
 | 405 |         def fromkeys(klass, iterable, value=None): | 
 | 406 |             "Emulate dict_fromkeys() in Objects/dictobject.c" | 
 | 407 |             d = klass() | 
 | 408 |             for key in iterable: | 
 | 409 |                 d[key] = value | 
 | 410 |             return d | 
 | 411 |         fromkeys = classmethod(fromkeys) | 
 | 412 |  | 
 | 413 | Now a new dictionary of unique keys can be constructed like this:: | 
 | 414 |  | 
 | 415 |     >>> Dict.fromkeys('abracadabra') | 
 | 416 |     {'a': None, 'r': None, 'b': None, 'c': None, 'd': None} | 
 | 417 |  | 
 | 418 | Using the non-data descriptor protocol, a pure Python version of | 
 | 419 | :func:`classmethod` would look like this:: | 
 | 420 |  | 
 | 421 |     class ClassMethod(object): | 
 | 422 |          "Emulate PyClassMethod_Type() in Objects/funcobject.c" | 
 | 423 |  | 
 | 424 |          def __init__(self, f): | 
 | 425 |               self.f = f | 
 | 426 |  | 
 | 427 |          def __get__(self, obj, klass=None): | 
 | 428 |               if klass is None: | 
 | 429 |                    klass = type(obj) | 
 | 430 |               def newfunc(*args): | 
 | 431 |                    return self.f(klass, *args) | 
 | 432 |               return newfunc | 
 | 433 |  |