Subscribes to events or to :class:`~pydispatch.properties.Property` updates

        Keyword arguments are used with the Event or Property names as keys
        and the callbacks as values::

            class Foo(Dispatcher):
                name = Property()

            foo = Foo()

            foo.bind(name=my_listener.on_foo_name_changed)
            foo.bind(name=other_listener.on_name,
                     value=other_listener.on_value)

        The callbacks are stored as weak references and their order is not
        maintained relative to the order of binding.

        **Async Callbacks**:

            Callbacks may be :term:`coroutine functions <coroutine function>`
            (defined using :keyword:`async def` or decorated with
            :func:`@asyncio.coroutine <asyncio.coroutine>`), but an event loop
            must be explicitly provided with the keyword
            argument ``"__aio_loop__"`` (an instance of
            :class:`asyncio.BaseEventLoop`)::

                import asyncio
                from pydispatch import Dispatcher

                class Foo(Dispatcher):
                    _events_ = ['test_event']

                class Bar(object):
                    def __init__(self):
                        self.got_foo_event = asyncio.Event()
                    async def wait_for_foo(self):
                        await self.got_foo_event.wait()
                        print('got foo!')
                    async def on_foo_test_event(self, *args, **kwargs):
                        self.got_foo_event.set()

                foo = Foo()
                bar = Bar()

                loop = asyncio.get_event_loop()
                foo.bind(test_event=bar.on_foo_test_event, __aio_loop__=loop)

                loop.run_until_complete(bar.wait_for_foo())

            This can also be done using :meth:`bind_async`.

            .. versionadded:: 0.1.0

def bind(self, **kwargs):
        """Subscribes to events or to :class:`~pydispatch.properties.Property` updates

        Keyword arguments are used with the Event or Property names as keys
        and the callbacks as values::

            class Foo(Dispatcher):
                name = Property()

            foo = Foo()

            foo.bind(name=my_listener.on_foo_name_changed)
            foo.bind(name=other_listener.on_name,
                     value=other_listener.on_value)

        The callbacks are stored as weak references and their order is not
        maintained relative to the order of binding.

        **Async Callbacks**:

            Callbacks may be :term:`coroutine functions <coroutine function>`
            (defined using :keyword:`async def` or decorated with
            :func:`@asyncio.coroutine <asyncio.coroutine>`), but an event loop
            must be explicitly provided with the keyword
            argument ``"__aio_loop__"`` (an instance of
            :class:`asyncio.BaseEventLoop`)::

                import asyncio
                from pydispatch import Dispatcher

                class Foo(Dispatcher):
                    _events_ = ['test_event']

                class Bar(object):
                    def __init__(self):
                        self.got_foo_event = asyncio.Event()
                    async def wait_for_foo(self):
                        await self.got_foo_event.wait()
                        print('got foo!')
                    async def on_foo_test_event(self, *args, **kwargs):
                        self.got_foo_event.set()

                foo = Foo()
                bar = Bar()

                loop = asyncio.get_event_loop()
                foo.bind(test_event=bar.on_foo_test_event, __aio_loop__=loop)

                loop.run_until_complete(bar.wait_for_foo())

            This can also be done using :meth:`bind_async`.

            .. versionadded:: 0.1.0

        """
        aio_loop = kwargs.pop('__aio_loop__', None)
        props = self.__property_events
        events = self.__events
        for name, cb in kwargs.items():
            if name in props:
                e = props[name]
            else:
                e = events[name]
            e.add_listener(cb, __aio_loop__=aio_loop)