Kannan Ekanath
Kannan Ekanath

Reputation: 17601

Python flattening my tuple structure

I am trying to have a python hierarchical data structure with a map and the value will be a tuple. In some cases the tuple will be of length 1. Python intelligently flattens the structure whenever the tuple is of length 1. Observe the example below which can be run in a python interpreter. In the "another_scenario" I expected the length to be 1 but it has drilled one level below and got the underlying steps. This totally screws up my tests because I rely on that being a tuple with the command, function_list, function list.

Question - Why does this happen? How do I ask python to not flatten it?

import os

def run():
    my_scenario = {
            "scenario_name" : 
            (   # Each scenario is a List of (command, function_list, function_list)
                # function_list = one function OR tuple of functions
                (
                    "command1",
                    (
                        os.path,
                        os.path.exists
                    ),
                    None
                ),
                (
                    "command2",
                    (
                        os.path,
                        os.path.exists
                    ),
                    None
                )
            )
        } 
    another_scenario = {
            "scenario_name" : 
            (
                (
                    "command1",
                    (
                        os.path,
                        os.path.exists
                    ),
                    None
                )
            )
    }
    for name in my_scenario:
        print "Full Scenario is %s" % str(my_scenario[name])
        print "Length should be 2 -> %s" % len(my_scenario[name])
    for name in another_scenario:
        print "Full Scenario is %s" % str(another_scenario[name])
        print "Length should be 1 -> %s" % len(another_scenario[name]) #Prints 3 as it drills one level down


if __name__ == "__main__":
    run()    

Upvotes: 0

Views: 370

Answers (1)

Martijn Pieters
Martijn Pieters

Reputation: 1122312

You need to add a comma:

another_scenario = {
        "scenario_name": 
        (
            (
                "command1",
                (
                    os.path,
                    os.path.exists
                ),
                None
            ),  # <- Note this comma
        )
}

to make that a tuple, otherwise it is just an expression. 1-element tuples can only be distinguished from expressions by the presence of a comma:

>>> (1)
1
>>> (1,)
(1,)
>>> type((1))
<type 'int'>
>>> type((1,))
<type 'tuple'>

In fact, it's the comma that defines tuples, not the parenthesis:

>>> 1,
(1,)
>>> 1, 2
(1, 2)

The parenthesis are only needed when you need to define an empty tuple:

>>> ()
()

Upvotes: 2

Related Questions