Python Forum
testing if this is a container type - Printable Version

+- Python Forum (https://python-forum.io)
+-- Forum: Python Coding (https://python-forum.io/Forum-Python-Coding)
+--- Forum: General Coding Help (https://python-forum.io/Forum-General-Coding-Help)
+--- Thread: testing if this is a container type (/Thread-testing-if-this-is-a-container-type)



testing if this is a container type - Skaperen - Jan-24-2019

in a function being passed an argument, it might be a single data type or it might be a container of some type. i need to do different callbacks depending on that. i am wondering if there is a way to test of some given argument is a container or not. even if it some programmer created type (it's just going to be passed back with some other data, so i don't need to understand that data any more than that). does anyone know how to do such a test?


RE: testing if this is a container type - ichabod801 - Jan-24-2019

You should really checkout the collections.abc module.


RE: testing if this is a container type - buran - Jan-24-2019

(Jan-24-2019, 07:01 PM)Skaperen Wrote: in a function being passed an argument, it might be a single data type or it might be a container of some type. i need to do different callbacks depending on that.

in addition to ichabood's suggestion, I would recommend to look at @functools.singledispatch


RE: testing if this is a container type - ichabod801 - Jan-24-2019

I'm not sure how that happened, buran, but you seem to have quoted Skaperen and attributed it to me.

Edit: If you select text from one post, and click the quote highlighted button for another post, it quotes the first poster and attributes it to the second poster.


RE: testing if this is a container type - buran - Jan-24-2019

(Jan-24-2019, 07:53 PM)ichabod801 Wrote: 'm not sure how that happened, buran, but you seem to have quoted Skaperen and attributed it to me.

Edit: If you select text from one post, and click the quote highlighted button for another post, it quotes the first poster and attributes it to the second poster.
yes, I know that, my error, sorry :-) Now I will fix it :-)


RE: testing if this is a container type - buran - Jan-24-2019

Here is an example with @functools.singledispatch

import collections.abc
import functools

@functools.singledispatch
def foo(arg):
    print("that's not container", type(arg))

@foo.register(collections.abc.Container)
def _(arg):
    print('Now that is container', type(arg))


test_items = [int(), str(), dict(), list()]

for item in test_items:
    foo(item)
Output:
that's not container <class 'int'> Now that is container <class 'str'> Now that is container <class 'dict'> Now that is container <class 'list'>
EDIT: Fixed the import - collections.abc instead of just collections. Importing just collections was giving an error with 3.7, although at home I think I test the code with 3.5. collections.abc was part of collections before 3.3


RE: testing if this is a container type - Skaperen - Jan-24-2019

oh dear, this program i'm doing needs to have str not be a container. yeah, i know it technically is a container. i didn't think about that, yet. but, buran's example made obvious. it's simple enough to check for str first.


RE: testing if this is a container type - buran - Jan-25-2019

You can always register separate callback for str. It will take precedence over the callback for the abstract class. Also it will propagate for any custom class that inherit from str.
import collections.abc
import functools
 
@functools.singledispatch
def foo(arg):
    print("that's not container", type(arg))
 
@foo.register(collections.abc.Container)
def _(arg):
    print('Now that is container', type(arg))
    
@foo.register(str)
def _(arg):
    print("that's str", type(arg))
    
class Foo(str):
    pass
 
 
test_items = [int(), str(), dict(), list(), Foo()]
 
for item in test_items:
    foo(item)
Output:
that's not container <class 'int'> that's str <class 'str'> Now that is container <class 'dict'> Now that is container <class 'list'> that's str <class '__main__.Foo'> >>>
Note that you can use different names for the registered callbacks so that you can distinguish and check which callback will be used for certain class.