[英]Python - Not repeating code with if statements, is there another way?
希望提高我的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))
我通常通過使用字典來避免很多ifs。 我將每個條件映射到字典並執行。 這是我的第一個建議:
我創建了一個添加幾個月的函數,因為timedelta沒有它。 然后,我使用re
獲得數字和字母作為元組。 因此,“ 4M”將是(“ 4”,“ M”)。 然后我將M映射到月份加法,所以4 *(添加月份功能),W映射加周,等等。
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)
如果我們期望得到不干凈的數據,則需要創建一個數據准備功能,以確保我們的數據采用我們希望數字寫字母的格式。 因為如果我們僅接收字母數據,我們的代碼將失敗。 代替try-catch,如果我們只有一個字母,我們可以添加1。這就是我的看法2:
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)
在data_prep函數中,您將在其中處理所有可能的不潔性:)
您可以使用re
提取數字部分和所有期間字符。
>>> 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:我將執行更多的錯誤檢查-上面的代碼只是建議使用稍多的pythonic方法來執行相同的操作。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.