Search code examples
pythontypesduck-typing

Is reuse of a function argument for multiple types in Python 3.4 pythonic, and how does it relate to duck typing? Should I split the function up?


I come from C# and Java, so lose typing is still new to me, it might show.

I have a function which shoots of a query to a a database to remove duplicates which have occurred lately. Say, withing the last 14 days or so. When the script runs daily I'd like it to only lookback using an integer of days like 14; however, sometimes I might want to supply a datetime and have it use it directly instead of calculating what date it would be by subtraction of an integer.

The following is pretty much what I have at the moment:

def clean_up_duplicates(dup_lookback):
    if hasattr(dup_lookback, 'strftime'):
        dup_start_str = dup_lookback.strftime('%Y-%m-%d %H:%M:%S')
    else:
        dup_start = date.today() - timedelta(days=dup_lookback)
        dup_start_str = dup_start.strftime('%Y-%m-%d %H:%M:%S')

    # ... continue on and use dup_start_str in a query.

Is this correct use of ducktyping? Is this pythonic?

My alternative, of the top of my head, is to split up in two functions:

def clean_up_duplicates_since_days(dup_lookback_days):
    dup_start_str = dup_lookback.strftime('%Y-%m-%d %H:%M:%S')
    __clean_up_duplicates(dup_start_str)

def clean_up_duplicates_since_datetime(dup_lookback_datetime):
    dup_start = date.today() - timedelta(days=dup_lookback)
    dup_start_str = dup_start.strftime('%Y-%m-%d %H:%M:%S')
    __clean_up_duplicates(dup_start_str)

def __clean_up_duplicates(dup_start_str):
    # ... continue on and use dup_start_str in a query.

(Coded this last bit in the browser, so might be off)


Solution

  • Duck typing means you assume that an object contains a function, and if it does then everything just works.

    If there's an alternate path to take if the function doesn't exist, catch it with a try/except.

    def clean_up_duplicates(dup_lookback):
        try:
            dup_start_str = dup_lookback.strftime('%Y-%m-%d %H:%M:%S')
        except AttributeError:
            dup_start = date.today() - timedelta(days=dup_lookback)
            dup_start_str = dup_start.strftime('%Y-%m-%d %H:%M:%S')