Out of curiosity I was discovering the potential of the Ellipsis
object in Python (...
), and I discovered it doesn't do a whole lot except for a handful of minor features. In an effort to make it useful, I decided to create the most fancy-pants constructor for a list that I could.
The function, super_list
, takes an arbitrary number of arguments to be added to the list. Here are the features:
super_list(multiple, arguments, provided) ->
Generates a list using the arguments provided. If an argument doesn't follow any of the special features below, it is just appended to the array at the proper nesting level. This example returns[multiple, arguments, provided]
, a list of the arguments.super_list(5, ..., 9) ->
Takes advantage of theEllipsis
object to create something that looks like "x to y", or a range. This particular example would produce a list containing[5,6,7,8,9]
, the number between 5 and 9.super_list(arg, array.move_up, higher_arg, array.move_down, lower_arg) ->
Sets the nesting level inside the list. Includingarray.move_up
orarray.move_down
moves up or down one level of nesting in the list. This example produces[arg, [higher_arg], lower_arg]
, moving up and down the array chain witharray.move_up
andarray.move_down
.
One last big example:
super_list("first level", 5, ..., 9, array.move_up, array.move_up, "second level", 10, ..., 15, array.move_down, "down one level")
produces
['first level', 5, 6, 7, 8, 9, [['second level', 10, 11, 12, 13, 14, 15], 'down one level']]
So this is my current implementation:
def get_in_list(lst, indexes):
"""Gets an item in a nested list by a list of indexes."""
return functools.reduce(operator.getitem, indexes, lst)
def super_list(*args):
"""Special initialization syntax for lists."""
curr_index = []
result = []
for index, item in enumerate(args): # Iterate over args with indexes
el_type = type(...) # Type of the Ellipsis object
if isinstance(item, el_type): # Case: Ellipsis range generator
if index == 0:
get_in_list(result, curr_index).append(item)
else:
get_in_list(result, curr_index).extend(list(range(args[index-1]+1, args[index+1])))
elif item == array.move_up: # Case: move up one level in list
get_in_list(result, curr_index).append([])
curr_index.append(len(get_in_list(result, curr_index))-1)
elif item == array.move_down: # Case: move down one level in list
try:
curr_index.pop()
except IndexError: # Silently catch if user tries to move down too far in the list
pass
else: # Case: No special syntax - regularly append item to list
get_in_list(result, curr_index).append(item)
return result
get_in_list
is a function used to get an item at a list of indexes. This means that a[0][1] == get_in_list(a, [0, 1])
.
My questions:
Is it too messy?
Is anything too long and could be implemented in a shorter way?
Is the program too confusing, and do you think it could be more verbose?
And obviously, any other comments you may want to add are appreciated. Thanks in advance!