30 | | - ``cls.__classcall__(cls, <some arguments>)`` |
31 | | |
32 | | If neither of these two methods are implemented, then the standard |
33 | | ``type.__call__(cls, <some arguments>)`` is called, which in turn |
34 | | uses :meth:`__new__` and :meth:`__init__` as usual (see Section |
35 | | "Basic Customization" in the Python Reference Manual). |
36 | | |
37 | | See ``sage.misc.classcall_metaclass.ClasscallMetaclass.__call__?`` |
38 | | for an example. |
39 | | |
40 | | Typical applications include the implementation of factories or of |
41 | | unique representation (see :class:`UniqueRepresentation`). Such |
42 | | features are traditionaly implemented by either using a wrapper |
43 | | function, or fiddling with :meth:`__new__`. |
44 | | |
45 | | The benefit, compared with fiddling directly with :meth:`__new__` |
46 | | is a clear separation of the three distinct roles: |
47 | | |
48 | | - :meth:`cls.__classcall__`: what cls(<...>) does |
49 | | - :meth:`cls.__new__`: memory allocation for a *new* instance |
50 | | - :meth:`cls.__init__`: initialization of a newly created instance |
51 | | |
52 | | The benefit, compared with using a wrapper function, is that the |
53 | | user interface has a single handle for the class:: |
54 | | |
55 | | sage: x = Partition([3,2,2]) |
56 | | sage: isinstance(x, Partition) # todo: not implemented |
57 | | |
58 | | instead of:: |
59 | | |
60 | | sage: isinstance(x, sage.combinat.partition.Partition_class) |
61 | | True |
62 | | |
63 | | Another difference is that :meth:`__classcall__` is inherited by |
64 | | subclasses, which may be desirable, or not. If not, one should |
65 | | instead define the method :meth:`__classcall_private__` which will |
66 | | not be called for subclasses. Specifically, if a class ``cls`` |
67 | | defines both methods ``__classcall__`` and |
68 | | ``__classcall_private__`` then, for any subclass ``sub`` of ``cls``: |
69 | | |
70 | | - ``cls(<args>)`` will call ``cls.__classcall_private__(cls, <args>)`` |
71 | | - ``sub(<args>)`` will call ``cls.__classcall__(sub, <args>)`` |
| 37 | TODO: find a good name for this metaclass. |
| 45 | def __get__(cls, instance, owner): |
| 46 | """ |
| 47 | This method implements instance binding behavior for nested classes. |
| 48 | |
| 49 | Suppose that a class ``Outer`` contains a nested class ``cls`` which |
| 50 | is an instance of this metaclass. For any object ``obj`` of ``cls``, |
| 51 | this method implements a instance binding behavior for ``obj.cls`` by |
| 52 | delegating it to ``cls.__classget__(Outer, obj, owner)`` if available. |
| 53 | Otherwise, ``obj.cls`` results in ``cls``, as usual. |
| 54 | |
| 55 | Similarily, a class binding as in ``Outer.cls`` is delegated |
| 56 | to ``cls.__classget__(Outer, None, owner)`` if available and |
| 57 | to ``cls`` if not. |
| 58 | |
| 59 | For technical details, and in particular the description of |
| 60 | the ``owner`` argument, see the Section ``Implementing |
| 61 | Descriptors`` in the Python reference manual. |
| 62 | |
| 63 | EXAMPLES: |
| 64 | |
| 65 | We show how to implement a nested class ``Outer.Inner`` with a |
| 66 | binding behavior, as if it was a method of ``Outer``: namely, |
| 67 | for ``obj`` an instance of ``Outer``, calling |
| 68 | ``obj.Inner(...)`` is equivalent to ``Outer.Inner(obj, ...)``:: |
| 69 | |
| 70 | sage: import functools |
| 71 | sage: from sage.misc.classcall_metaclass import ClasscallMetaclass |
| 72 | sage: class Outer: |
| 73 | ... class Inner(object): |
| 74 | ... __metaclass__ = ClasscallMetaclass |
| 75 | ... @staticmethod |
| 76 | ... def __classget__(cls, instance, owner): |
| 77 | ... print "calling __classget__(%s, %s, %s)"%( |
| 78 | ... cls, instance, owner) |
| 79 | ... if instance is None: |
| 80 | ... return cls |
| 81 | ... return functools.partial(cls, instance) |
| 82 | ... def __init__(self, instance): |
| 83 | ... self.instance = instance |
| 84 | sage: obj = Outer() |
| 85 | sage: bar = obj.Inner() |
| 86 | calling __classget__(<class '__main__.Inner'>, <__main__.Outer instance at 0x...>, __main__.Outer) |
| 87 | sage: bar.instance == obj |
| 88 | True |
| 89 | |
| 90 | Calling ``Outer.Inner`` returns the (unbinded) class as usual:: |
| 91 | |
| 92 | sage: Inner = Outer.Inner |
| 93 | calling __classget__(<class '__main__.Inner'>, None, __main__.Outer) |
| 94 | sage: Inner |
| 95 | <class '__main__.Inner'> |
| 96 | sage: type(bar) is Inner |
| 97 | True |
| 98 | |
| 99 | ..warning:: Inner has to be a new style class (i.e. a subclass of object). |
| 100 | |
| 101 | ..warning:: calling ``obj.Inner`` does no longer return a class:: |
| 102 | |
| 103 | sage: bind = obj.Inner |
| 104 | calling __classget__(<class '__main__.Inner'>, <__main__.Outer instance at ...>, __main__.Outer) |
| 105 | sage: bind |
| 106 | <functools.partial object at 0x...> |
| 107 | """ |
| 108 | if hasattr(cls, "__classget__"): |
| 109 | return cls.__classget__(cls, instance, owner) |
| 110 | else: |
| 111 | return cls |
| 112 | |
| 117 | Let ``cls`` be a class in ``ClasscallMetaclass``, and consider |
| 118 | a call of the form: |
| 119 | |
| 120 | ``cls(<some arguments>)`` |
| 121 | |
| 122 | If ``cls`` defines a method ``__classcall_private__``, then |
| 123 | this results in a call to:: |
| 124 | |
| 125 | - ``cls.__classcall_private__(cls, <some arguments>)`` |
| 126 | |
| 127 | Otherwise, if ``cls`` has a method ``__classcall__``, then instead |
| 128 | the following is called: |
| 129 | |
| 130 | - ``cls.__classcall__(cls, <some arguments>)`` |
| 131 | |
| 132 | If neither of these two methods are implemented, then the standard |
| 133 | ``type.__call__(cls, <some arguments>)`` is called, which in turn |
| 134 | uses :meth:`__new__` and :meth:`__init__` as usual (see Section |
| 135 | "Basic Customization" in the Python Reference Manual). |
| 136 | |
| 207 | ..rubric: Discussion |
| 208 | |
| 209 | Typical applications include the implementation of factories or of |
| 210 | unique representation (see :class:`UniqueRepresentation`). Such |
| 211 | features are traditionaly implemented by either using a wrapper |
| 212 | function, or fiddling with :meth:`__new__`. |
| 213 | |
| 214 | The benefit, compared with fiddling directly with :meth:`__new__` |
| 215 | is a clear separation of the three distinct roles: |
| 216 | |
| 217 | - :meth:`cls.__classcall__`: what cls(<...>) does |
| 218 | - :meth:`cls.__new__`: memory allocation for a *new* instance |
| 219 | - :meth:`cls.__init__`: initialization of a newly created instance |
| 220 | |
| 221 | The benefit, compared with using a wrapper function, is that the |
| 222 | user interface has a single handle for the class:: |
| 223 | |
| 224 | sage: x = Partition([3,2,2]) |
| 225 | sage: isinstance(x, Partition) # todo: not implemented |
| 226 | |
| 227 | instead of:: |
| 228 | |
| 229 | sage: isinstance(x, sage.combinat.partition.Partition_class) |
| 230 | True |
| 231 | |
| 232 | Another difference is that :meth:`__classcall__` is inherited by |
| 233 | subclasses, which may be desirable, or not. If not, one should |
| 234 | instead define the method :meth:`__classcall_private__` which will |
| 235 | not be called for subclasses. Specifically, if a class ``cls`` |
| 236 | defines both methods ``__classcall__`` and |
| 237 | ``__classcall_private__`` then, for any subclass ``sub`` of ``cls``: |
| 238 | |
| 239 | - ``cls(<args>)`` will call ``cls.__classcall_private__(cls, <args>)`` |
| 240 | - ``sub(<args>)`` will call ``cls.__classcall__(sub, <args>)`` |
| 241 | |
| 242 | |
| 243 | |