1

I'm curious, is there a standard approach to dealing with long lists in the Python community, and in particular, is there any antipathy toward doing blank lines followed by comments to break up a particularly long list, e.g. of tuples, or in a dict, etc.?

For example, I'm developing a GUI application in wxPython, and am defining the keyboard shortcut mappings to . Is this fairly Pythonic?

accelerator_table = wx.AcceleratorTable([
    # Case accelerators
    (CTRL, ord('S'), EventIds.SAVE_CASE),
    (CTRL_SHIFT, ord('S'), EventIds.RENAME_CASE),
    (CTRL, wx.WXK_DELETE, EventIds.REMOVE_CASE),
    (CTRL_SHIFT, wx.WXK_DELETE, EventIds.DELETE_CASE),

    # Project accelerators
    (CTRL_ALT_SHIFT, ord('S'), EventIds.RENAME_PROJECT),
    (ALT, wx.WXK_DELETE, EventIds.REMOVE_PROJECT),
    (ALT_SHIFT, wx.WXK_DELETE, EventIds.DELETE_PROJECT),

    # Help accelerators
    (NORMAL, wx.WXK_F1, EventIds.HELP),
    (NORMAL, wx.WXK_F2, EventIds.LAUNCH_MANUAL),
    (NORMAL, wx.WXK_F12, EventIds.ABOUT),
    ...
])

The details aren't particularly important, but I'd like to write in a style that will not annoy other programmers along the way, and therefore to decide right now whether this pattern is worth keeping around.

Edit: Just to clarify: I'm not intending to put anything beyond that single blank line between sections in the list. That seems like it should minimize any confusion on the part of someone reading through the code.

2
  • 1
    If it makes the code easier to understand, who cares about "pythonic"?
    – Izkata
    Commented Mar 22, 2013 at 19:04
  • 2
    A reasonable question. My thought was simply that "easier to read" has some things that are constant, but some things that vary by convention in the community. What's easier to read for a Java gal isn't necessarily the same as what's easier to read for a Python guy isn't necessarily the same as what's easier to read for a Lisp gal. Conventions aren't hard rules, but they're worth at least being aware of. Commented Mar 22, 2013 at 19:09

2 Answers 2

3

Looking at the OP's initial approach, it is immediately obvious to me what it's doing. I don't see that there are readability or maintainability problems with this at all, nor do I see that it violates any commonly-accepted Python conventions or idioms. It's clear, and it uses minimal syntactic boilerplate and extraneous operations to achieve its goal. I recommend sticking with this approach.

The implementation suggested by Demian's answer seems to create more problems than it solves. Returning a list from a property is usually not a good idea, because it creates an interface that will look identical to an attribute, but will exhibit bizarre behavior if used as such, e.g. t.file.extend(t.project) will not do what most users would expect, and will "fail silently", causing potentially confounding bugs.

The OP could use instance attributes or class fields instead of properties, but I'm not sure an object-oriented approach has much utility here (i.e. it seems to be using class syntax without employing actual OOP concepts).

But the suggestion to separate the tuple-list aggregate into multiple smaller lists, that are then concatenated and passed to wx.AcceleratorTable, seems sensible. The "right" approach is mostly a matter of preference, though I still prefer the OP's initial approach because it involves less list manipulation, and doesn't have any readability issues that I see.

3
  • 1
    +1, you should never make something more complex if it also makes it harder to understand for no real benefit.
    – Izkata
    Commented Mar 22, 2013 at 19:08
  • See my update. I wasn't thinking overly clearly when I originally answered. Commented Mar 22, 2013 at 19:28
  • @DemianBrecht: Entirely understandable; I edited my answer to reflect your update, and agree that your revised suggestion is more palatable (I was typing my answer as you were editing yours). Commented Mar 22, 2013 at 19:48
1

[snip due to people not reading the /entire/ response]

To answer your actual question, whitespace is fine to break things up visually, but I'd recommend that the number of lines that you use should not exceed that of the number of lines between other entities in your code (such as number of lines between functions within a class, or module-level classes or functions). As Python's readability is so heavily based on whitespace, using more whitespace in a particular method to break up internal code might initially throw off a reader looking to grok it at a glance.

Edit based on comments:

>>> accel_file = [('a','b'), ('c', 'd')]
>>> accel_project = [('e', 'f'), ('g', 'h')]
>>> 
>>> from itertools import chain
>>> list(chain(accel_file, accel_project))
[('a', 'b'), ('c', 'd'), ('e', 'f'), ('g', 'h')]

Grouping as such allows your code to be self-documenting. chain is an overly complex solution in this particular case (I was writing code using at the time of the answer :P), but could be useful if doing something like:

accelerators = [accel_file, acces_project, ...]
list(chain(*accelerators))

But for the simple case, concatenation (+) would be preferred.

12
  • 1
    A couple thoughts: (1) I'm not sure that actually increases readability. It's abstracted things quite a bit, which can be a good thing in many cases, but in this case, I think it's less obvious what's going on, which I'd like to avoid, as that decreases maintainability substantially.. (2) That abstraction is a much larger step than is necessary even if we do split it up. I don't see a good reason to use a class instead of just a set of list variables, e.g. help_accel = [(a, b, c), (d, e, f), ...]. I'm not sure we really need to abstract a list of tuples to a class. Commented Mar 22, 2013 at 17:55
  • Also, as I noted in my edit, I certainly would never put more than a single blank line between elements (as in the list I put in my example). Commented Mar 22, 2013 at 18:26
  • @ChrisKrycho: Ah, in my un-caffeinated state, I didn't see fully what was going on. Rather than using a class, I'd still set a local reference to each logical block and then chain them to create the list being fed into AcceleratorTable. Commented Mar 22, 2013 at 18:28
  • @ChrisKrycho: See edit. Really, it's just personal preference, but this makes the intention of each portion of your list easier to grok. It's /clear/ what is intended to go where (and therefore increases readability). Commented Mar 22, 2013 at 18:31
  • 2
    Sure, and that makes a lot more sense. Out of curiosity, though: why use chain() instead of just concatenating with +, e.g. accel_file + accel_project? Commented Mar 22, 2013 at 18:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.