Whats the pythonic way to handle empty *args when creating a set?

21,597

Solution 1

Is there a way to pass an "entire set" argument to SubsetOutput, so you can bury the conditional inside its call rather than have an explicit if? This could be None or [], for example.

# Pass None to use full subset.
def Export(source, target, *args, sep=','):
    for item in source:
        SubsetOutput(WriteFlatFile(target), args or None).send(item[0])

# Pass an empty list [] to use full subset. Even simpler.
def Export(source, target, *args, sep=','):
    for item in source:
        SubsetOutput(WriteFlatFile(target), args).send(item[0])

If not, I would go with the two loop solution, assuming the loop really is a single line. It reads well and is a reasonable use case for a little bit of code duplication.

def Export(source, target, *args, sep=','):
    if args:
        for item in source:
            SubsetOutput(WriteFlatFile(target), args).send(item[0])
    else:
        for item in source:
            FullOutput(WriteFlatFile(target)).send(item[0])

Solution 2

Just check its not none, you don't have to create a separate argument

def test(*args):
    if not args:
        return #break out
    return True #or whatever you want

Solution 3

How about this:

def MyFunc(argument, *args):
    ( DoSomething for i in (filter(args.__contains__ ,argument) if args else argument) )
Share:
21,597
justin cress
Author by

justin cress

Updated on December 20, 2020

Comments

  • justin cress
    justin cress over 3 years

    Defining a function,

    MyFunction(argument, *args): [do something to argument[arg] for arg in *args]

    if *args is empty, the function doesn't do anything, but I want to make the default behavior 'use the entire set if length of *args == 0'

    def Export(source, target, *args, sep=','):
        for item in source:
            SubsetOutput(WriteFlatFile(target), args).send(item[0])
    

    I don't want to check the length of args on every iteration, and I can't access the keys of item in source until the iteration begins...

    so i could

    if len(args) != 0:
       for item in source:
    
    else
       for item in source:
    

    which will probably work but doesn't seem 'pythonic' enough?

    is this (is there) a standard way to approach *args or **kwargs and default behavior when either is empty?

    More Code:

    def __coroutine(func):
        """
        a decorator for coroutines to automatically prime the routine
        code and method from 'curous course on coroutines and concurrency'
        by david beazley www.dabeaz.com
        """
    
        def __start(*args, **kwargs):
            cr = func(*args, **kwargs)
            next(cr)
            return cr
        return __start
    
    
    def Export(source, target, *args, sep=','):
        if args:
            for item in source:
                SubsetOutput(WriteFlatFile(target, sep), args).send(item)
        else:
            for item in source:
                WriteFlatFile(target, sep).send(item)
    
    @__coroutine
    def SubsetOutput(target, *args):
        """
        take *args from the results and pass to target
    
        TODO
        ----
        raise exception when arg is not in result[0]
        """
        while True:
            result = (yield)
            print([result.arg for arg in result.dict() if arg in args])
            target.send([result.arg for arg in result.dict if arg in args])
    
    
    @__coroutine
    def WriteFlatFile(target, sep):
        """
        take set of results to a flat file
    
        TODO
        ----
        """
        filehandler = open(target, 'a')
        while True:
            result = (yield)
            line = (sep.join([str(result[var]) for
                            var in result.keys()])).format(result)+'\n'
            filehandler.write(line)
    
  • justin cress
    justin cress over 13 years
    the two loop solution seems to be the easiest to implement (in this case), though I guess I was just more concerned with the general case where the loop may not be a single line. Trying to avoid code repetition.
  • PatrickT
    PatrickT almost 4 years
    "Just check it's not none" is an ambiguous statement, because if args is None: will not work, as *args are set to (). It must really be if not args: (as your code states). So really your opening sentence ought to be "Just check it's not args" ! Thanks to your answer for helping me work that one out.