Python不使用if语句重复代码,还有其他方法吗?

2024-04-26 04:19:50 发布

您现在位置:Python中文网/ 问答频道 /正文

希望提高我的python和编码技能。我有一个函数,可以为时间添加一个特定的时间段。 我通过:

1M, 7D, 6M, 2H, M等。。并返回值。我觉得我在重复我自己。有没有比这更像Python的方法?你知道吗


def add_timeframe(time, timeframe):                                                                                                                                     

    if 'H' in timeframe:                                                                                                                                                
    ┆   try:                                                                                                                                                            
    ┆   ┆   period = int(re.sub('\D', '', timeframe))                                                                                                                   
    ┆   ┆   return convert_datetime(time + datetime.timedelta(hours=period))                                                                                            

    ┆   except ValueError:                                                                                                                                              
    ┆   ┆   return convert_datetime(time + datetime.timedelta(hours=1))                                                                                                 


    if 'D' in timeframe:                                                                                                                                                
    ┆   try:                                                                                                                                                            
    ┆   ┆   period = int(re.sub('\D', '', timeframe))                                                                                                                   
    ┆   ┆   return convert_datetime(time + datetime.timedelta(days=period))                                                                                             

    ┆   except ValueError:                                                                                                                                              
    ┆   ┆   return convert_datetime(time + datetime.timedelta(days=1))                                                                                                  


    if 'W' in timeframe:                                                                                                                                                
    ┆   try:                                                                                                                                                            
    ┆   ┆   period = int(re.sub('\D', '', timeframe))                                                                                                                   
    ┆   ┆   return convert_datetime(time + datetime.timedelta(weeks=period))                                                                                            

    ┆   except ValueError:                                                                                                                                              
    ┆   ┆   return convert_datetime(time + datetime.timedelta(weeks=period))                                                                                            


    if 'M' in timeframe:                                                                                                                                                
    ┆   try:                                                                                                                                                            
    ┆   ┆   period = int(re.sub('\D', '', timeframe))                                                                                                                   
    ┆   ┆   return convert_datetime(time + datetime.timedelta(days=365/12*period))                                                                                      

    ┆   except ValueError:                                                                                                                                              
    ┆   ┆   return convert_datetime(time + datetime.timedelta(days=365/12))

Tags: inreconvertdatetimereturniftimedays
2条回答

我通常用字典来避免很多“如果”。我将每个条件映射到字典并执行。这是我的第一张照片:

我创建了一个用于添加月份的函数,因为timedelta没有它。然后使用re将数字和字母作为元组。所以“4M”应该是('4','M')。然后我将M映射为月加法,因此4*(add months函数),W表示add weeks等

import calendar
import datetime
import re


# add month hack
def add_month(num_months, date=None):
    '''Add N months'''

    assert num_months > 0, 'Positive N only'

    if date is None:
        date = datetime.datetime.now()

    for num in range(num_months):
        month_days = calendar.monthrange(date.year, date.month)[1]
        dt = date + datetime.timedelta(days=month_days)

        if dt.day != date.day:
             dt.replace(day=1) - datetime.timedelta(days=1)
        else:
            dt

        date = dt
    return dt



def delta(data, pattern):
    # dict instead of lots of ifs

    time_convert = {'M': lambda x : add_month(x),
                   'W': lambda x :datetime.timedelta(weeks=x),
                   'D': lambda x: datetime.timedelta(days=x),
                   'H': lambda x: datetime.timedelta(hours=x),
                          }


    _ = [re.match(pattern, item).groups() for item in data]

    return [time_convert.get(letter)(int(number))for number, letter in _] 

# test 1
data = ['1M', '7D', '4M', '2H']
pattern = '(\d+)(\w+)'

s = delta(data, pattern)
print(s)

如果我们期待不干净的数据,我们需要创建一个数据准备功能,将确保我们的数据是在一个格式,我们希望digitsletter(s)。因为如果我们只收到字母数据,我们的代码就会失败。如果我们只有一个字母,我们可以添加1,而不是try catch。这将是我的第二步:

import calendar
import datetime
import re


# add month hack
def add_month(num_months, date=None):
    '''Add N months'''

    assert num_months > 0, 'Positive N only'

    if date is None:
        date = datetime.datetime.now()

    for num in range(num_months):
        month_days = calendar.monthrange(date.year, date.month)[1]
        dt = date + datetime.timedelta(days=month_days)

        if dt.day != date.day:
             dt.replace(day=1) - datetime.timedelta(days=1)
        else:
            dt

        date = dt
    return dt


def data_prep(data, check_patter='\d+'):
    '''Our data preparation happens here'''

    _ = [bool(re.search(check_patter,item)) for item in data]

    for index, truth in enumerate(_):
        if not truth:
            data[index] = '1'+data[index]

    return data




def delta(data, pattern):

    time_convert = {'M': lambda x : add_month(x),
                'W': lambda x :datetime.timedelta(weeks=x),
                'D': lambda x: datetime.timedelta(days=x),
                'H': lambda x: datetime.timedelta(hours=x),
                       }


    # clean data. if M  > 1M
    data = data_prep(data)
    _ = [re.match(pattern, item).groups() for item in data]

    return [time_convert.get(letter)(int(number))for number, letter in _] 


data = ['1M', '7D', '4M', '2H','H']

pattern = '(\d+)(\w+)'


s = delta(data, pattern)

print(s)

在数据准备功能中,您将处理所有可能的不干净:)

您可以使用re在一次go中提取数字部分和所有句点字符。。你知道吗

>>> import re
>>> inp = ["1M", "7D", "6M", "2H", "M"]
>>> [re.findall('(\d)?(M|D|H)', x) for x in inp]
[[('1', 'M')], [('7', 'D')], [('6', 'M')], [('2', 'H')], [('', 'M')]]

>>> extracted = [re.findall('(\d)?(M|D|H)', x) for x in inp]
>>> [(int(x[0][0] or '1'), x[0][1]) for x in extracted if x] # Filter out invalids.
[(1, 'M'), (7, 'D'), (6, 'M'), (2, 'H'), (1, 'M')]

然后您可以使用convert_datetime(..)和您在原始代码中正在做的其他东西。你知道吗

PS:我会执行更多的错误检查上面的代码只是建议一个稍微更python的方式做同样的事情。你知道吗

相关问题 更多 >