diff --git a/atools/_memoize_decorator.py b/atools/_memoize_decorator.py
index 9aeaa97..62b064c 100644
--- a/atools/_memoize_decorator.py
+++ b/atools/_memoize_decorator.py
@@ -16,8 +16,6 @@ from typing import Any, Callable, Hashable, Mapping, Optional, Tuple, Type, Unio
 Decoratee = Union[Callable, Type]
 Keygen = Callable[..., Tuple[Any]]
 
-_default_db_path = Path.home() / '.memoize'
-
 
 class _MemoZeroValue:
     pass
@@ -310,19 +308,7 @@ class _SyncMemoize(_MemoizeBase):
             self.reset_key(key)
 
 
-_Memoize = Union[_AsyncMemoize, _SyncMemoize]
-
-_all_decorators = set()
-
-
-def memoize(
-    _decoratee: Optional[Decoratee] = None,
-    *,
-    db: Union[bool, Path, str] = False,
-    duration: Optional[Union[int, float, timedelta]] = None,
-    keygen: Optional[Keygen] = None,
-    size: Optional[int] = None,
-):
+class _Memoize:
     """Decorates a function call and caches return value for given inputs.
 
     If 'db' is provided, memoized values will be saved to disk and reloaded during initialization.
@@ -492,62 +478,79 @@ def memoize(
             @memoize(db='~/bar_memoize')
             def bar() -> Any: ...
     """
-    if _decoratee is None:
-        return partial(memoize, db=db, duration=duration, keygen=keygen, size=size)
-    
-    if inspect.isclass(_decoratee):
-        assert not db, 'Class memoization not allowed with db.'
 
-        class WrappedMeta(type(_decoratee)):
-            # noinspection PyMethodParameters
-            @memoize(duration=duration, size=size)
-            def __call__(cls, *args, **kwargs):
-                return super().__call__(*args, **kwargs)
+    _default_db_path = Path.home() / '.memoize'
+    _all_decorators = set()
 
-        class Wrapped(_decoratee, metaclass=WrappedMeta):
-            pass
+    @staticmethod
+    def __call__(
+            _decoratee: Optional[Decoratee] = None,
+            *,
+            db: Union[bool, Path, str] = False,
+            duration: Optional[Union[int, float, timedelta]] = None,
+            keygen: Optional[Keygen] = None,
+            size: Optional[int] = None,
+    ):
+        if _decoratee is None:
+            return partial(memoize, db=db, duration=duration, keygen=keygen, size=size)
+
+        if inspect.isclass(_decoratee):
+            assert not db, 'Class memoization not allowed with db.'
+
+            class WrappedMeta(type(_decoratee)):
+                # noinspection PyMethodParameters
+                @memoize(duration=duration, size=size)
+                def __call__(cls, *args, **kwargs):
+                    return super().__call__(*args, **kwargs)
+
+            class Wrapped(_decoratee, metaclass=WrappedMeta):
+                pass
+
+            return type(_decoratee.__name__, (Wrapped,), {'__doc__': _decoratee.__doc__})
+
+        if isinstance(db, (str, Path)):
+            db = connect(f'{db}')
+        elif isinstance(db, bool):
+            if db:
+                db = connect(f'{_Memoize._default_db_path}')
+            else:
+                db = None
+
+        duration = timedelta(seconds=duration) if isinstance(duration, (int, float)) else duration
+        assert (duration is None) or (duration.total_seconds() > 0)
+        assert (size is None) or (size > 0)
+        fn = _decoratee
+        default_kwargs: Mapping[str, Any] = {
+            k: v.default for k, v in inspect.signature(fn).parameters.items()
+        }
+
+        if inspect.iscoroutinefunction(_decoratee):
+            decorator_cls = _AsyncMemoize
+        else:
+            decorator_cls = _SyncMemoize
 
-        return type(_decoratee.__name__, (Wrapped,), {'__doc__': _decoratee.__doc__})
+        # noinspection PyArgumentList
+        decorator = decorator_cls(
+            db=db,
+            default_kwargs=default_kwargs,
+            duration=duration,
+            fn=fn,
+            keygen=keygen,
+            size=size,
+        ).get_decorator()
 
-    if isinstance(db, (str, Path)):
-        db = connect(f'{db}')
-    elif isinstance(db, bool):
-        if db:
-            db = connect(f'{_default_db_path}')
-        else:
-            db = None
-
-    duration = timedelta(seconds=duration) if isinstance(duration, (int, float)) else duration
-    assert (duration is None) or (duration.total_seconds() > 0)
-    assert (size is None) or (size > 0)
-    fn = _decoratee
-    default_kwargs: Mapping[str, Any] = {
-        k: v.default for k, v in inspect.signature(fn).parameters.items()
-    }
-
-    if inspect.iscoroutinefunction(_decoratee):
-        decorator_cls = _AsyncMemoize
-    else:
-        decorator_cls = _SyncMemoize
-
-    # noinspection PyArgumentList
-    decorator = decorator_cls(
-        db=db,
-        default_kwargs=default_kwargs,
-        duration=duration,
-        fn=fn,
-        keygen=keygen,
-        size=size,
-    ).get_decorator()
-
-    _all_decorators.add(decorator)
-    
-    return wraps(_decoratee)(decorator)
+        _Memoize._all_decorators.add(decorator)
 
+        return wraps(_decoratee)(decorator)
 
-def reset_all() -> None:
-    for decorator in _all_decorators:
-        decorator.memoize.reset()
+    @staticmethod
+    def reset_all() -> None:
+        for decorator in _Memoize._all_decorators:
+            decorator.memoize.reset()
+
+    @staticmethod
+    def set_default_db_path(path: Union[Path, str]) -> None:
+        _Memoize._default_db_path = Path(f'{path}')
 
 
-memoize.reset_all = reset_all
+memoize = _Memoize()
diff --git a/setup.py b/setup.py
index b65347c..da3d160 100644
--- a/setup.py
+++ b/setup.py
@@ -2,7 +2,7 @@ from setuptools import find_packages, setup
 
 setup(
     name='atools',
-    version='0.10.0',
+    version='0.10.1',
     packages=find_packages(),
     python_requires='>=3.6',
     url='https://github.com/cevans87/atools',

Allow global override of default_db_path in memoize decorator
If we enable override of the default_db_path, we can make memoize decorators look a little cleaner. So, rather than something like

```
db_path = Path.cwd() / 'foo_db'

@memoize(db=db_path)
def foo(): ...

@memoize(db=db_path)
def bar() ...

def __main__: ...
```

We could have
```
@memoize(db=True)
def foo(): ...

@memoize(db=True)
def bar() ...

def __main__:
    memoize.set_default_db_path(Path.cwd() / 'foo_db')
```
diff --git a/test/test_memoize_decorator.py b/test/test_memoize_decorator.py
index 5f13cc8..0cf0a76 100644
--- a/test/test_memoize_decorator.py
+++ b/test/test_memoize_decorator.py
@@ -9,10 +9,19 @@ import pytest
 from sqlite3 import connect, Connection
 from tempfile import NamedTemporaryFile
 from typing import Callable, FrozenSet, Hashable, Iterable, Tuple, Union
-from unittest.mock import call, MagicMock, patch
+from unittest.mock import call, MagicMock, patch, PropertyMock
 from weakref import ref
 
 
+def get_table_len(db) -> int:
+    if isinstance(db, bool):
+        db = connect(f'{memoize._default_db_path}')
+    elif isinstance(db, (Path, str)):
+        db = connect(f'{db}')
+    # noinspection SqlResolve
+    return len(db.execute("SELECT name FROM sqlite_master where type='table'").fetchall())
+
+
 @pytest.fixture
 def async_lock() -> MagicMock:
     with patch.object(test_module, 'AsyncLock', side_effect=None) as async_lock:
@@ -23,8 +32,10 @@ def async_lock() -> MagicMock:
 def db(request) -> Union[bool, Connection, Path, str]:
     with NamedTemporaryFile() as f:
         if request.param is bool:
-            with patch.object(test_module, '_default_db_path') as default_db_path:
-                default_db_path.__str__.return_value = f.name
+            with patch.object(
+                    type(memoize), '_default_db_path', new_callable=PropertyMock
+            ) as default_db_path:
+                default_db_path.return_value = Path(f.name)
                 yield True
         else:
             yield request.param(f.name)
@@ -619,14 +630,6 @@ async def test_keygen_awaits_awaitable_parts() -> None:
 
 def test_db_creates_table_for_each_decorator(db: Union[bool, Connection, Path, str]) -> None:
     
-    def get_table_len(_db) -> int:
-        if isinstance(_db, bool):
-            _db = connect(f'{test_module._default_db_path}')
-        elif isinstance(_db, (Path, str)):
-            _db = connect(f'{_db}')
-        # noinspection SqlResolve
-        return len(_db.execute("SELECT name FROM sqlite_master where type='table'").fetchall())
-
     assert get_table_len(db) == 0
 
     @memoize(db=db)
@@ -848,3 +851,16 @@ def test_reset_call_with_db_resets_call(db: Union[bool, Connection, Path, str])
     for i in range(10):
         foo(i)
     assert body.call_count == 11
+
+
+def test_set_default_db_path_uses_given_path() -> None:
+    with NamedTemporaryFile() as f, patch.object(type(memoize), '_default_db_path'):
+        memoize.set_default_db_path(f.name)
+
+        assert get_table_len(f.name) == 0
+
+        @memoize(db=True)
+        def foo():
+            ...
+
+        assert get_table_len(f.name) == 1

pip install -e .[u2f]
parse_log_pytest
requirements.txt
nose mock pytest
apt-get update apt-get install -y gcc
3.6
requirements.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
-e git+https://github.com/cevans87/atools.git@84813d73106ad59ab4def34e7b337f50df8bddb0#egg=atools
attrs==22.2.0
certifi==2021.5.30
dataclasses==0.8
frozendict==2.4.6
importlib-metadata==4.8.3
iniconfig==1.1.1
mock==5.2.0
nose==1.3.7
packaging==21.3
pluggy==1.0.0
py==1.11.0
pyparsing==3.1.4
pytest==7.0.1
tomli==1.2.3
typing_extensions==4.1.1
zipp==3.6.0

name: atools
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - certifi=2021.5.30=py36h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.3=he6710b0_2
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=1.1.1w=h7f8727e_0
  - pip=21.2.2=py36h06a4308_0
  - python=3.6.13=h12debd9_1
  - readline=8.2=h5eee18b_0
  - setuptools=58.0.4=py36h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - wheel=0.37.1=pyhd3eb1b0_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - attrs==22.2.0
      - dataclasses==0.8
      - frozendict==2.4.6
      - importlib-metadata==4.8.3
      - iniconfig==1.1.1
      - mock==5.2.0
      - nose==1.3.7
      - packaging==21.3
      - pluggy==1.0.0
      - py==1.11.0
      - pyparsing==3.1.4
      - pytest==7.0.1
      - tomli==1.2.3
      - typing-extensions==4.1.1
      - zipp==3.6.0
prefix: /opt/conda/envs/atools

test/test_memoize_decorator.py::test_db_creates_table_for_each_decorator[bool] test/test_memoize_decorator.py::test_db_reloads_values_from_disk[bool] test/test_memoize_decorator.py::test_reset_removes_values_on_disk[bool] test/test_memoize_decorator.py::test_db_expires_memo[bool] test/test_memoize_decorator.py::test_db_memoizes_multiple_values[bool] test/test_memoize_decorator.py::test_db_with_size_expires_lru[bool] test/test_memoize_decorator.py::test_db_with_duration_expires_stale_values[bool] test/test_memoize_decorator.py::test_db_memoizes_frozenset[bool] test/test_memoize_decorator.py::test_reset_call_with_db_resets_call[bool] test/test_memoize_decorator.py::test_set_default_db_path_uses_given_path
test/test_memoize_decorator.py::test_zero_args test/test_memoize_decorator.py::test_class_function test/test_memoize_decorator.py::test_keyword_same_as_default test/test_memoize_decorator.py::test_sync_size test/test_memoize_decorator.py::test_sync_exception test/test_memoize_decorator.py::test_expire_current_call test/test_memoize_decorator.py::test_expire_old_call test/test_memoize_decorator.py::test_expire_old_item_does_not_expire_new test/test_memoize_decorator.py::test_expire_head_of_line_refresh_does_not_stop_eviction test/test_memoize_decorator.py::test_size_le_zero_raises test/test_memoize_decorator.py::test_expire_le_zero_raises test/test_memoize_decorator.py::test_args_overlaps_kwargs_raises test/test_memoize_decorator.py::test_sync_reset_clears_cache test/test_memoize_decorator.py::test_works_with_property test/test_memoize_decorator.py::test_sync_locks_sync test/test_memoize_decorator.py::test_sync_does_not_async_lock test/test_memoize_decorator.py::test_async_no_event_loop_does_not_raise test/test_memoize_decorator.py::test_memoizes_class test/test_memoize_decorator.py::test_memoizes_class_with_metaclass test/test_memoize_decorator.py::test_reset_all_resets_class_decorators test/test_memoize_decorator.py::test_reset_all_resets_function_decorators test/test_memoize_decorator.py::test_memoize_class_preserves_doc test/test_memoize_decorator.py::test_keygen_overrides_default test/test_memoize_decorator.py::test_db_creates_table_for_each_decorator[connect] test/test_memoize_decorator.py::test_db_creates_table_for_each_decorator[Path] test/test_memoize_decorator.py::test_db_creates_table_for_each_decorator[str] test/test_memoize_decorator.py::test_db_reloads_values_from_disk[connect] test/test_memoize_decorator.py::test_db_reloads_values_from_disk[Path] test/test_memoize_decorator.py::test_db_reloads_values_from_disk[str] test/test_memoize_decorator.py::test_reset_removes_values_on_disk[connect] test/test_memoize_decorator.py::test_reset_removes_values_on_disk[Path] test/test_memoize_decorator.py::test_reset_removes_values_on_disk[str] test/test_memoize_decorator.py::test_db_expires_memo[connect] test/test_memoize_decorator.py::test_db_expires_memo[Path] test/test_memoize_decorator.py::test_db_expires_memo[str] test/test_memoize_decorator.py::test_db_memoizes_multiple_values[connect] test/test_memoize_decorator.py::test_db_memoizes_multiple_values[Path] test/test_memoize_decorator.py::test_db_memoizes_multiple_values[str] test/test_memoize_decorator.py::test_db_with_size_expires_lru[connect] test/test_memoize_decorator.py::test_db_with_size_expires_lru[Path] test/test_memoize_decorator.py::test_db_with_size_expires_lru[str] test/test_memoize_decorator.py::test_db_with_duration_expires_stale_values[connect] test/test_memoize_decorator.py::test_db_with_duration_expires_stale_values[Path] test/test_memoize_decorator.py::test_db_with_duration_expires_stale_values[str] test/test_memoize_decorator.py::test_db_memoizes_frozenset[connect] test/test_memoize_decorator.py::test_db_memoizes_frozenset[Path] test/test_memoize_decorator.py::test_db_memoizes_frozenset[str] test/test_memoize_decorator.py::test_sync_reset_call_resets_one test/test_memoize_decorator.py::test_reset_call_before_expire_resets_one test/test_memoize_decorator.py::test_reset_call_with_db_resets_call[connect] test/test_memoize_decorator.py::test_reset_call_with_db_resets_call[Path] test/test_memoize_decorator.py::test_reset_call_with_db_resets_call[str]
atools/_memoize_decorator.py setup.py
atools/_memoize_decorator.py setup.py