From 2e3e639ddbaa6ba59891564df8e66b018d38900f Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Mon, 31 Jul 2017 18:50:25 -0700 Subject: [PATCH] Make DateOffset (partially) immutable, cache _params for __eq__ speedup --- pandas/tseries/offsets.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/pandas/tseries/offsets.py b/pandas/tseries/offsets.py index 2a120a0696836..7e727107ab87d 100644 --- a/pandas/tseries/offsets.py +++ b/pandas/tseries/offsets.py @@ -11,6 +11,7 @@ from dateutil.relativedelta import relativedelta, weekday from dateutil.easter import easter from pandas._libs import tslib, Timestamp, OutOfBoundsDatetime, Timedelta +from pandas.util import cache_readonly import functools import operator @@ -184,10 +185,17 @@ def __add__(date): ) _use_relativedelta = False _adjust_dst = False + _typ = "dateoffset" # default for prior pickles normalize = False + def __setattr__(self, key, value): + if key in ['n', '_offset'] and hasattr(self, key): + raise TypeError('%s is intended to be immutable; "%s" ' + 'cannot be changed.' % (self.__class__, key)) + object.__setattr__(self, key, value) + def __init__(self, n=1, normalize=False, **kwds): self.n = int(n) self.normalize = normalize @@ -308,6 +316,7 @@ def copy(self): def _should_cache(self): return self.isAnchored() and self._cacheable + @cache_readonly def _params(self): all_paras = dict(list(vars(self).items()) + list(self.kwds.items())) if 'holidays' in all_paras and not all_paras['holidays']: @@ -369,13 +378,13 @@ def __eq__(self, other): if not isinstance(other, DateOffset): return False - return self._params() == other._params() + return self._params == other._params def __ne__(self, other): return not self == other def __hash__(self): - return hash(self._params()) + return hash(self._params) def __call__(self, other): return self.apply(other) @@ -808,7 +817,7 @@ def rollforward(self, dt): @apply_wraps def apply(self, other): - # calcurate here because offset is not immutable + # calculate here because offset is not immutable daytime = self._get_daytime_flag() businesshours = self._get_business_hours_by_sec() bhdelta = timedelta(seconds=businesshours) @@ -2728,7 +2737,7 @@ def __eq__(self, other): # This is identical to DateOffset.__hash__, but has to be redefined here # for Python 3, because we've redefined __eq__. def __hash__(self): - return hash(self._params()) + return hash(self._params) def __ne__(self, other): if isinstance(other, compat.string_types):