PEP 8 and list comprehension

后端 未结 4 1887
小鲜肉
小鲜肉 2021-01-17 18:27

I seem to have hit a bit of a problem with PEP 8.

I am using list comprehension which is longer than 79 characters long. So my text editor is screaming at me to do s

相关标签:
4条回答
  • 2021-01-17 18:42

    When using pep8 common sense applies. If you can't fit a line of logic within 80 character it is almost always a sign that this line has to be rewritten. And it is true in this case as I can't for one even start to try to comprehend what is that line supposed to do.

    But if you move it to a much more readable format then not only your line count will go up, but also your readability level, leaving you a lot of place for proper variable names like user instead of i. This will make your own maintenance in the future much easier, not to mention if someone else ever have to look at it.

    So to put this example into actual code, that is what I would do with it (with a nice function wrap to make the sample much easier to read!):

    j = {'collection': [{'id': 1, 'user_id': 1}]}
    
    def get_qualified_users(users):
        qualified_users = []
        for user in users:
            if user and user['user_id']:
                qualified_users.append((user['user_id'], user['id']))
        return qualified_users
    
    print(get_qualified_users(j['collection']))
    

    You can easily copy/paste it into your interpetor to see that it works. And more than that - it is extremely easy to maintain and follow, with clear api encapsulated in a sealed function.

    0 讨论(0)
  • 2021-01-17 18:47

    if you want to stick strictly to pep8 then the hanging indent is your friend.

    return [
        (i['user_id'], i['id'])
        for i in j['collection']
        if i and i['user_id']]
    
    0 讨论(0)
  • 2021-01-17 18:54

    While I'm a fan of relaxing the strict-80-char limit, and (as mentioned in comment) so is Raymond Hettinger in this compelling talk from PyCon 2015, in this particular case, the cleanest thing might be to just split it into two lines:

    valid_things = (i for i in j['collection'] if i and i['user_id'])
    return [(i['user_id'], i['id']) for i in valid_things]
    

    This way the "filtering" and "selection" logic are clearly separated and presented in a more readable way than jamming them together.

    Another option for the functionally-inclined:

    return map(itemgetter('user_id', 'id'), valid_things)
    
    0 讨论(0)
  • 2021-01-17 19:02

    You just need to indent the second line properly:

    return [(i['user_id'], i['id']) for i in j['collection']
            if i and i['user_id']]
    

    Confirmed with PEP8 online, but let me know whether it works for you as well.

    Personally, I dislike expression and source together but the condition separate. I'd rather clearly see the expression alone, not the condition. Highlight what you get. So I would do one of these:

    return [(i['user_id'], i['id'])
            for i in j['collection'] if i and i['user_id']]
    
    return [(i['user_id'], i['id'])
            for i in j['collection']
            if i and i['user_id']]
    

    Clarification: This is how I'd indent/break. I didn't consider the variable names, as I just wanted to give a direct answer and explain what the PEP8 error was and how to fix it, because noone else had.

    0 讨论(0)
提交回复
热议问题