facets of objects
eugene.leitl at lrz.uni-muenchen.de
eugene.leitl at lrz.uni-muenchen.de
Wed Oct 25 14:43:22 EDT 2000
(((slightly edited to foil the spambots)))
From: kragen at pobox dot com (Kragen Sitaker)
In Python, it's really simple to create an object that acts like a
built-in object: a file, a dictionary, a sequence. You just define the
methods the built-in object implements --- "implement the protocol" ---
and everything that expects the built-in object will then be able to
talk to your object.
Not so in Perl. You can create objects that act like built-in objects
--- at least in some cases --- but there are several different more or
less clumsy ways of implementing different built-in objects.
In Python, there are magical methods called __getattr__ and
__setattr__, which allow you to create virtual attributes of objects,
so that trying to set an attribute calls __setattr__ instead of setting
the attribute, and trying to read a nonexistent attribute calls
__getattr__ instead of raising an AttributeError. (Perl has AUTOLOAD,
which does mostly the same thing.)
Both of the Python ways are really simple, but somewhat inadequate.
Your pseudo-file and pseudo-dictionary objects will have attributes
files and dictionaries don't; proving that client code doesn't depend
on those attributes requires looking through the client code at every
variable that could hold an instance of a pseudo-file object and
verifying that the attributes aren't used.
__getattr__ has a more serious problem; it only works for attributes
that don't really exist. So if your clients use one of the attribute
names you used in your implementation --- presumably not knowing you
used them --- they will get screwed.
In KeyKOS and EROS, it is common for a single object to implement
several different interfaces, such as a read-only interface, a
read-write interface, and a write-only interface; clients holding a
capability to one interface should not automatically be able to get
capabilities to other interfaces, although some interfaces will have
methods that allow a client to request capabilities to other interfaces
to the same object.
All of these problems have a solution in common, I think: "facets". A
"facet" is a mapping of selectors, such as method or attribute names or
EROS order codes, into attributes of the object; it can be used
anywhere the object can. Since most kinds of objects don't need
multiple facets, you shouldn't have to do extra work just to use a
language that implements facets; you should only have to do extra work
when you want to define or use a new facet.
Here's a pure-Python implementation that shows what the interface to
facet functionality could look like. It works insofar as the names you
specify get mapped correctly; it's broken insofar as the Facet objects
it creates still have four object attributes and five class attributes
accessible from any Facet object. I think I could make it work in C.
class Facet:
def __init__(self, object, dict, getattr=None, setattr=None):
self.__object = object
self.__dict = dict
self.__getattr = getattr
self.__setattr = setattr
def __getattr__(self, attrname):
if self.__getattr is not None:
return self.__getattr(self.__object, attrname)
elif self.__dict.has_key(attrname):
return getattr(self.__object, self.__dict[attrname])
else:
raise AttributeError, attrname
def __setattr__(self, attrname, value):
if attrname in ('_Facet__object', '_Facet__dict', '_Facet__getattr',
'_Facet__setattr'):
self.__dict__[attrname] = value
elif self.__setattr is not None:
return self.__setattr(self.__object, attrname, value)
elif self.__dict.has_key(attrname):
return setattr(self.__object, self.__dict[attrname], value)
else:
raise AttributeError, attrname
--
<kragen at pobox dot com> Kragen Sitaker <http://www.pobox.com/~kragen/>
Perilous to all of us are the devices of an art deeper than we ourselves
possess.
-- Gandalf the Grey [J.R.R. Tolkien, "Lord of the Rings"]
--
Unsubscribes to kragen-hacks-unsubscribe at kragen.dnaco.net; public followups to
kragen-discuss at kragen.dnaco.net. Hacks posted to this list are in the
public domain, unless otherwise specified; I hereby disclaim any intellectual-
property interest in hacks posted here without a copyright notice.
More information about the Python-list
mailing list