<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:

def search(target_types=None, timeout=12, tries=3):
    '''
    Performs a search via SSDP to discover resources.

    Args:
        target_types (sequence of strings): A sequence of :term:`resource types`
            to search for. For convenience, this can also be a single string. If
            provided, then this function will make individual requests searching
            for specific targets - this is sometimes required as some devices
            will not respond unless they are specifically requested by the search. 
            
            If not given, then a search won't be broadcast, but we will still
            listen for SSDP notification responses.

        timeout (int / float): Overall time in seconds for how long to wait for
            before no longer listening for responses.

        tries (int): How many times to send out a search request - this will be
            spread out over the timeout period.

    Yields:
        :py:class:`Discovery` instances describing each result found - any
        duplicate results will be filtered out by this function.
    '''
    if isinstance(target_types, six.string_types):
        target_types = [target_types]

    seen = set()
    timeout = float(timeout) / tries
    type_filter = set(target_types) if target_types else None
    with contextlib.closing(make_socket()) as sock:
        for i in range(tries):
            if target_types:
                for target_type in target_types:
                    request_via_socket(sock, target_type)
            for response in responses_from_socket(sock, timeout):
                discovery = Discovery(response)
                if discovery in seen:
                    continue
                seen.add(discovery)
                if type_filter and discovery.type not in target_types:
                    continue
                yield discovery