def update(*args, **kwds): # args[0] -> 'self'
        """
        DS.update(E, **F) -> None.

        Update DS from the union of DictSet/dict/iterable E and F.
        
        If E has a .keys() method, does:
            for k in E:
                DS[k] |= set(E[k])
            
        If E lacks .keys() method, does:
            for (k, v) in E:
                DS[k] |= set(v)
            
        In either case, this is followed by:
            for k in F:
                DS[k] |= set(F[k])

        DS|=E  <==> DS.update(E)
        """
        # check the length of args
        if len(args) > 2:
            raise TypeError(
            'DictSet expected at most 1 arguments, got %d' % (len(args) - 1))

        # Make sure args can be mapped to a DictSet before
        # we start adding them.
        elif len(args) == 2:
            obj = args[1]

            # if obj is a DictType we can avoid checking
            # to make sure it is hashable an iterable
            if type(obj) == DictSet:
                pass
            
            # Check using duck typing
            elif hasattr(obj, '__getitem__'):

                # obj is dict or dict subclass
                if hasattr(obj, 'keys'):
                    for k, val in obj.items():
                        if not hasattr(k,'__hash__'):
                            raise TypeError(
                                "unhashable type: '%s'" % type(k).__name__)
                        
                        if not hasattr(val,'__iter__'):
                            if not isinstance(val, str):
                                raise TypeError(
                        "'%s' object is not iterable" % type(val).__name__)

                # obj is list/tuple or list/tuple subclass
                else:
                    for item in obj:
                        try:
                            (k, val)=item
                        except:
                            raise TypeError(
                                  'could not unpack arg to key/value pairs')

                        if not hasattr(k,'__hash__'):
                            raise TypeError(
                                "unhashable type: '%s'" % type(k).__name__)
                        
                        if not hasattr(val,'__iter__'):
                            if not isinstance(val, str):
                                raise TypeError(
                        "'%s' object is not iterable" % type(val).__name__)

            # obj is not iterable, e.g. an int, float, etc.
            else:
                raise TypeError(
                         "'%s' object is not iterable" % type(obj).__name__)
                    
        # check the keyword arguments
        for (k, val) in kwds.items():
            # unhashable keyword argumnents don't make it to the point 
            # so we just need to check that the values are iterable
            if not hasattr(val,'__iter__'):
                if not isinstance(val, str):
                    raise TypeError(
                         "'%s' object is not iterable" % type(val).__name__)

        # At this point we can be fairly certain the args and kwds 
        # will successfully initialize. Now we can go back through
        # args and kwds and add them to ds
        if len(args) == 2:
            obj = args[1]

            # obj is dict or dict subclass
            if hasattr(obj, 'keys'):
                for k, val in obj.items():
                    if not k in args[0].keys():
                        args[0][k] = set(val)
                    args[0][k] |= set(val)

            # obj is list/tuple or list/tuple subclass
            else:
                for item in obj:
                    (k, val) = item
                    if not k in args[0].keys():
                        args[0][k] = set(val)
                    args[0][k] |= set(val)

        # Now add keyword arguments
        for (k, val) in kwds.items():
            if not k in args[0].keys():
                args[0][k] = set(val)
            args[0][k] |= set(val)

        DS.update(E, **F) -> None.

        Update DS from the union of DictSet/dict/iterable E and F.
        
        If E has a .keys() method, does:
            for k in E:
                DS[k] |= set(E[k])
            
        If E lacks .keys() method, does:
            for (k, v) in E:
                DS[k] |= set(v)
            
        In either case, this is followed by:
            for k in F:
                DS[k] |= set(F[k])

        DS|=E  <==> DS.update(E)
        
recipes/Python/577702_DictSet__specialized_Pythcontainer_datatype/recipe-577702.py