HTTP request for a single URL or list of URLs based on arguments provided
__call__ really confuses me. Type checking is the way to go for readability. On top of that, if you need to accept new types later, all you need to do is add an if statement.

In my opinion, if you absolutely want the brevity of __call__, accepting multiple types of arguments is fine, and so is returning multiple types (as is the case with many builtin and standard library functions). It is important that you mention this in the documentation, though.



Some other questionable things:


Instead of comparing type directly, you can use isinstance:

if isinstance(url_or_list_of, str):
    ...

url_or_list_of is a somewhat unfriendly name for a public API. How about url_or_list_of_urls?
It's good that you provide a 'clean exit' method. __del__ isn't the right method to override, however, since the implementation is CPython-specific, and it may never actually be called. Instead, try defining __enter__ and __exit__:

class AioRequest:
    ...
    def __enter__(self):
        return self
        # This should be all in most cases,
        # unless you want to do something with `self` before returning
    ...
    def __exit__(self, exc_type, exc_value, exc_traceback):
        self._session.close()


You can then use with:

  with AioRequest() as request:
      # __enter__ called
      response = request( ... )
  # __exit__ called