How to determine type of nested data structures in Python?

后端 未结 2 731
攒了一身酷
攒了一身酷 2021-01-12 07:55

I am currently translating some Python to F#, specifically neural-networks-and-deep-learning .

To make sure the data structures are correctly translated the details o

2条回答
  •  情话喂你
    2021-01-12 08:20

    One way to do it by hand would be:

    def type_spec_iterable(obj, name):
        tps = set(type_spec(e) for e in obj)
        if len(tps) == 1:
            return name + "<" + next(iter(tps)) + ">"
        else:
            return name + ""
    
    
    def type_spec_dict(obj):
        tps = set((type_spec(k), type_spec(v)) for (k,v) in obj.iteritems())
        keytypes = set(k for (k, v) in tps)
        valtypes =  set(v for (k, v) in tps)
        kt = next(iter(keytypes)) if len(keytypes) == 1 else "?"
        vt = next(iter(valtypes)) if len(valtypes) == 1 else "?"
        return "dict<%s, %s>" % (kt, vt)
    
    
    def type_spec_tuple(obj):
        return "tuple<" + ", ".join(type_spec(e) for e in obj) + ">"
    
    
    def type_spec(obj):
        t = type(obj)
        res = {
            int: "int",
            str: "str",
            bool: "bool",
            float: "float",
            type(None): "(none)",
            list: lambda o: type_spec_iterable(o, 'list'),
            set: lambda o: type_spec_iterable(o, 'set'),
            dict: type_spec_dict,
            tuple: type_spec_tuple,
        }.get(t, lambda o: type(o).__name__)
        return res if type(res) is str else res(obj)
    
    
    if __name__ == "__main__":
        class Foo(object):
            pass
        for obj in [
            1,
            2.3,
            None,
            False,
            "hello",
            [1, 2, 3],
            ["a", "b"],
            [1, "h"],
            (False, 1, "2"),
            set([1.2, 2.3, 3.4]),
            [[1,2,3],[4,5,6],[7,8,9]],
            [(1,'a'), (2, 'b')],
            {1:'b', 2:'c'},
            [Foo()], # todo - inheritance?
        ]:
            print repr(obj), ":", type_spec(obj)
    

    This prints:

    1 : int
    2.3 : float
    None : (none)
    False : bool
    'hello' : str
    [1, 2, 3] : list
    ['a', 'b'] : list
    [1, 'h'] : list
    (False, 1, '2') : tuple
    set([2.3, 1.2, 3.4]) : set
    [[1, 2, 3], [4, 5, 6], [7, 8, 9]] : list>
    [(1, 'a'), (2, 'b')] : list>
    {1: 'b', 2: 'c'} : dict
    [<__main__.Foo object at 0x101de6c50>] : list
    

    There's a question of how far you want to take it, and how deeply to check, with trade-offs between speed and accuracy. For example, do you want to go through all the items in a large list? Do you want to handle custom types (and tracking down common ancestors of those types)?

    Worth a read, though I'm not sure it's applicable, this PEP on type hints.

提交回复
热议问题