Alexander C
Alexander C

Reputation: 4047

How to hint python3.6 that parameter must be sized and iterable both?

I have a function that requires parameter to be both Sized and Iterable at the same time.

def foo(items):
    print(len(items))
    for i in item:
        print(i)

I thought that I can use standard typing module from python3.5+ and write this:

from  typing import Collection, Any

def foo(items: Collection[Any]):
    print(len(items))
    for i in item:
        print(i)



foo([1, 2, 3])
# PyCharm warns: Expected type 'Collection', got 'List[int]' instead.

Collection looks like what I need: class typing.Collection(Sized, Iterable[T_co], Container[T_co])

Why it causes warning?

What should i do to hint parameter as both Iterable and Sized?

Upvotes: 2

Views: 586

Answers (2)

beruic
beruic

Reputation: 5876

A dirty fix to make Python 3.5 happy is to use Union[Sized, Iterable[Any]].

It is dirty, because using this type annotation says that it should be either sized OR iterable, not sized AND iterable. The current Pycharm (2018.1) accepts this, and it runs.


UPDATE: I have found a way to use Collections in Python versions < 3.6. Before 3.6 Sequence is basically what Collection is in 3.6 (See here and here). In 3.6 a Sequence is basically a reversible Collection (see here), and this gave me issues, because a python set is not a sequence (it is not reversible) so I patched it with the following import code:

if sys.version_info >= (3, 6):
    from typing import Collection
else:
    from typing import Sequence, TypeVar

    T = TypeVar('T')
    Collection = Sequence[T]

Upvotes: 0

ShadowRanger
ShadowRanger

Reputation: 155526

Collection was only introduced in 3.6; odds are, your version of PyCharm doesn't recognize it yet.

There is no built-in that describes a sized, iterable container in 3.5, so you can't use this annotation in 3.5, at least, not without writing your own typing type, which PyCharm may or may not recognize.

Upvotes: 4

Related Questions