Yet Another PEP: Interface Adapter Mechanism __adapt__
robin.thomas at starmedia.net
Wed Mar 21 13:23:09 CET 2001
At 04:30 AM 3/21/01 -0500, Clark C. Evans wrote:
>Thank you all for your feedback and support with the first
>pass of this PEP. Below is a second attempt. The context and
>motivation sections are identical. Here are the major changes:
> * __query__ is renamed __adapt__ (adapter pattern)
> * __adapt__ now takes a class instance (instead of a DNS string)
> * __adapt__ now returns None if the lookup was unsuccessful
> * straw-man adapt function is detailed
> * the title of this PEP is updated respectively
This is very good. It actually can assimilate my idea for abstract type
checking via a __type__ method.
I also see that adapt() works to assimilate isinstance(), and probably
could assimilate issubclass(). I support that work, but I see that it gives
some complexity to the meaning of the return value -- in adapter-like
cases, you want to return self or an adapter of self; in test-like cases,
you want to return a boolean. I also think that is very cool.
I like "adapt" better than "query".
I also think that this function is a candidate to be an operator in the
future. The two quotes you mention in the PEP, to me at least, boil down to:
Quote 1: "The object may have the answer, so ask it about the identifier."
Quote 2: "The identifier may have the answer, so ask it about the object."
This makes me think of adapt() as a binary op just as +, ^, divmod, etc.
A word that works nicely as an operator name, especially a simple word that
novices can grasp quickly, would be ideal as a name for this new feature.
like(obj, ident, options=None)
# future operator "like" and "not like"
a like b # equiv to like(obj,ident)
a not like b # equiv to not like(obj,ident,"test")
2) "is" with builtin isa() or even just adapt()
a is b # adapt(a,b) as adapt written below
a is not b # not adapt(a,b,"test")
adapt(obj, ident, options=None)
Suggested impls for adapt:
# the like version
# ! uses builtins/ops as shorthand
def like(obj, ident, options=None):
# if same object, TRUE
if obj is ident: return 1
obj_type = type(obj)
# if one is the concrete type of another,
# or if they have the same concrete type, TRUE
if obj_type is ident: return 1
ident_type = type(obj)
if obj_type is ident_type or obj is ident_type: return 1
# seems that isinstance() and issubclass() can be implemented
# here if we return true cases and let the false cases fall
# through to the __like__ check.
retval = 0
if ident_type is ClassType:
if obj_type is InstanceType and isinstance(obj, ident): return 1
elif obj_type is ClassType and issubclass(obj, ident): return 1
# __like__, if a "builtin", is actually in the type methods
# table, not a real named attribute. obj.__like__ is just
# the way for instances to emulate the builtin method. Right?
# So the code below is pseudo-code for what would happen
# at the C level.
# try the obj's type first
retval = obj_type.slot('__like__')(obj, ident)
# else try the ident
retval = ident_type.slot('__like__')(ident, obj)
# options hook (if still needed)
And the implementations for some built-in types:
if hasattr(self, "__like__"): return self.__like__(ident)
All the others are wide open. If the types module gets some abstract type
objects like Mapping or Sequence or even things like Mutable, the __like__
slot exists to implement a type hierarchy.
I considered using ClassType's slot function to implement isinstance() and
issubclass(), or at least issubclass(). Maybe that's still a good idea.
StarMedia Network, Inc.
robin.thomas at starmedia.net
More information about the Python-list