En Thu, 15 Oct 2009 13:24:18 -0300, Rami Chowdhury <rami.chowdh...@gmail.com> escribió:

On Thu, 15 Oct 2009 09:11:00 -0700, Austin Bingham <austin.bing...@gmail.com> wrote:

On Thu, Oct 15, 2009 at 5:15 PM, Gabriel Genellina
<gagsl-...@yahoo.com.ar> wrote:
En Thu, 15 Oct 2009 11:42:20 -0300, Austin Bingham
<austin.bing...@gmail.com> escribió:
I think you didn't understand correctly Anthony Tolle's suggestion:

py> class Foo:
...   def __init__(self, name): self.name = name
...
py> objs = [Foo('Joe'), Foo('Jim'), Foo('Tom'), Foo('Jim')]
py> objs

I understand Anthony perfectly. Yes, I can construct a dict as you
specify, where all of the keys map to values with name attributes
equal to the key. My point is that dict doesn't really help me enforce
that beyond simply letting me set it up; it doesn't care about the
values at all, just the keys.

Perhaps this is an overly naive solution, but could you not define a class that implemented the set interface but used a dict for internal storage, and use that? You'd still have uniqueness (by dict key, which your class would define as object name) and as a bonus, retrievability by name, which set wouldn't give you.

Like this?

from collections import MutableSet

class KeyedSet(MutableSet):
    """A set with a custom element comparison function."""

    def __init__(self, iterable, key=lambda x: x):
"""Create a KeyedSet from iterable; key function determines uniqueness.

        `key` must be a callable taking a single argument; it is
        applied to every item in the iterable, and its result
        is used to determine set membership. That is, if key(item)
        returns the same thing for two items, only one of them will
        be in the set."""

        self._items = dict((key(item),item) for item in iterable)
        self._key = key

    # NOT a classmethod because self.key must be transferred too!
    # Fortunately it is always called as self._from_iterable(...)
    # in _abccoll.py
    def _from_iterable(self, iterable):
        return type(self)(iterable, key=self._key)

    def add(self, value):
        """Return True if it was added, False if already there."""
        key = self._key(value)
        if key in self._items: return False
        self._items[key] = value
        return True

    def discard(self, value):
        """Return True if it was deleted, False if not there."""
        key = self._key(value)
        if key not in self._items: return False
        del self._items[key]
        return True

    def clear(self):
        self._items.clear()

    def copy(self):
        return type(self)(self._items.values(), key=self._key)

    def __iter__(self):
        return iter(self._items.values())

    def __contains__(self, value):
        try: return self._key(value) in self._items
        except Exception: return False

    def __len__(self):
        return len(self._items)

    def __repr__(self):
        return "%s(%r)" % (type(self).__name__, self._items.values())


def demo():
  class Foo(object):
    def __init__(self, name):
      self.name = name
    def __repr__(self):
      return "%s(%r)" % (type(self).__name__, self.name)

  objs = [Foo('Joe'), Foo('Jim'), Foo('Tom'), Foo('Jim')]
  print objs
  s = KeyedSet(objs, key=lambda o:o.name)
  print len(s), s
  s.add(Foo('Joe'))
  print len(s), s
  moe = Foo('Moe')
  print "moe in s", moe in s
  s.add(moe)
  print "moe in s", moe in s
  print "'moe' in s", 'moe' in s
  s2 = set([Foo('Luc'), Foo('Jim'), Foo('Dan')])
  print "s | s2", s | s2
  print "s & s2", s & s2
  s3 = KeyedSet(s2, key=lambda o:o.name)
  print "s3 - s", s3 - s
  print "s - s3", s - s3
  print "s.copy()", s.copy()

demo()

--
Gabriel Genellina

--
http://mail.python.org/mailman/listinfo/python-list

Reply via email to