Using object or Any for wide type annotations?

Whenever I can’t know in advance the type of an input I tend to use Any for annotation; i.e.

def narrow_int_type(obj: Any) -> int:
    ...

While surfing though I sometimes see developers prefer using object rather than Any. Is there a particular difference? Should the first be preferred? I heard an argument that Any is not as safe as using object but I don’t exactly know why.

I think the argument is:

If you say object then the type checker will only allow operations which will work on every object, so it’s really restrictive. So obj.func() would be an error because generic objects don’t have a func attribute.

If you say Any then the type checker will leave you alone and assume you know what you’re doing.

Ah, makes sense, thanks. Marking as resolved.

One small thing to add is that Any should be the last resort, not the first.

For example, taking a very simple example from the thread,

from typing import Callable


def narrow_int_type[T:int](obj: Callable[[],T]) -> T:
    """Narrow an object to a type."""
    return obj()

def foob() -> int:
    """..."""
    return 1

def barb() -> str:
    """..."""
    return "a"

narrow_int_type(foob)
narrow_int_type(barb)

# Or, if int is invariant,
def narrow_int_type(obj: Callable[[],int]) -> int:
    """Narrow an object to a type."""
    return obj()

This would allow a type checker to use the typing to verify instead of just looking the other way at the main