diff --git a/CHANGELOG.md b/CHANGELOG.md
index d1c3008a..50d72395 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,9 @@
 * Enhancements
     * Raise `TypeError` if trying to set choices/completions on argparse action that accepts no arguments
     * Create directory for the persistent history file if it does not already exist
+    * Added `set_choices_function()`, `set_choices_method()`, `set_completer_function()`, and `set_completer_method()`
+    to support cases where this functionality needs to be added to an argparse action outside of the normal
+    `parser.add_argument()` call.
 
 ## 0.9.15 (July 24, 2019)
 * Bug Fixes
diff --git a/cmd2/argparse_custom.py b/cmd2/argparse_custom.py
index 5432314b..2a7be287 100644
--- a/cmd2/argparse_custom.py
+++ b/cmd2/argparse_custom.py
@@ -94,6 +94,14 @@ Tab Completion:
     as dynamic. Therefore it is up to the developer to validate if the user has typed an acceptable value for these
     arguments.
 
+    The following functions exist in cases where you may want to manually add choice providing function/methods to
+    an existing argparse action. For instance, in __init__() of a custom action class.
+
+        set_choices_function(action, func)
+        set_choices_method(action, method)
+        set_completer_function(action, func)
+        set_completer_method(action, method)
+
 CompletionItem Class:
     This class was added to help in cases where uninformative data is being tab completed. For instance,
     tab completing ID numbers isn't very helpful to a user without context. Returning a list of CompletionItems
@@ -223,6 +231,9 @@ class CompletionItem(str):
         self.description = desc
 
 
+############################################################################################################
+# Class and functions related to ChoicesCallable
+############################################################################################################
 class ChoicesCallable:
     """
     Enables using a callable as the choices provider for an argparse argument.
@@ -241,6 +252,48 @@ class ChoicesCallable:
         self.to_call = to_call
 
 
+def _set_choices_callable(action: argparse.Action, choices_callable: ChoicesCallable) -> None:
+    """
+    Set the choices_callable attribute of an argparse Action
+    :param action: action being edited
+    :param choices_callable: the ChoicesCallable instance to use
+    :raises: TypeError if used on incompatible action type
+    """
+    # Verify consistent use of parameters
+    if action.choices is not None:
+        err_msg = ("None of the following parameters can be used alongside a choices parameter:\n"
+                   "choices_function, choices_method, completer_function, completer_method")
+        raise (TypeError(err_msg))
+    elif action.nargs == 0:
+        err_msg = ("None of the following parameters can be used on an action that takes no arguments:\n"
+                   "choices_function, choices_method, completer_function, completer_method")
+        raise (TypeError(err_msg))
+
+    setattr(action, ATTR_CHOICES_CALLABLE, choices_callable)
+
+
+def set_choices_function(action: argparse.Action, choices_function: Callable[[], Iterable[Any]]) -> None:
+    """Set choices_function on an argparse action"""
+    _set_choices_callable(action, ChoicesCallable(is_method=False, is_completer=False, to_call=choices_function))
+
+
+def set_choices_method(action: argparse.Action, choices_method: Callable[[Any], Iterable[Any]]) -> None:
+    """Set choices_method on an argparse action"""
+    _set_choices_callable(action, ChoicesCallable(is_method=True, is_completer=False, to_call=choices_method))
+
+
+def set_completer_function(action: argparse.Action,
+                           completer_function: Callable[[str, str, int, int], List[str]]) -> None:
+    """Set completer_function on an argparse action"""
+    _set_choices_callable(action, ChoicesCallable(is_method=False, is_completer=True, to_call=completer_function))
+
+
+def set_completer_method(action: argparse.Action,
+                         completer_method: Callable[[Any, str, str, int, int], List[str]]) -> None:
+    """Set completer_method on an argparse action"""
+    _set_choices_callable(action, ChoicesCallable(is_method=True, is_completer=True, to_call=completer_method))
+
+
 ############################################################################################################
 # Patch _ActionsContainer.add_argument with our wrapper to support more arguments
 ############################################################################################################
@@ -291,7 +344,17 @@ def _add_argument_wrapper(self, *args,
           See the header of this file for more information
 
     :return: the created argument action
+    :raises ValueError on incorrect parameter usage
     """
+    # Verify consistent use of arguments
+    choices_callables = [choices_function, choices_method, completer_function, completer_method]
+    num_params_set = len(choices_callables) - choices_callables.count(None)
+
+    if num_params_set > 1:
+        err_msg = ("Only one of the following parameters may be used at a time:\n"
+                   "choices_function, choices_method, completer_function, completer_method")
+        raise (ValueError(err_msg))
+
     # Pre-process special ranged nargs
     nargs_range = None
 
@@ -345,34 +408,17 @@ def _add_argument_wrapper(self, *args,
     # Create the argument using the original add_argument function
     new_arg = orig_actions_container_add_argument(self, *args, **kwargs)
 
-    # Verify consistent use of arguments
-    choices_params = [new_arg.choices, choices_function, choices_method, completer_function, completer_method]
-    num_params_set = len(choices_params) - choices_params.count(None)
-
-    if num_params_set > 1:
-        err_msg = ("Only one of the following parameters may be used at a time:\n"
-                   "choices, choices_function, choices_method, completer_function, completer_method")
-        raise (ValueError(err_msg))
-    elif num_params_set > 0 and new_arg.nargs == 0:
-        err_msg = ("None of the following parameters can be used for this type of action:\n"
-                   "choices, choices_function, choices_method, completer_function, completer_method")
-        raise (TypeError(err_msg))
-
     # Set the custom attributes
     setattr(new_arg, ATTR_NARGS_RANGE, nargs_range)
 
     if choices_function:
-        setattr(new_arg, ATTR_CHOICES_CALLABLE,
-                ChoicesCallable(is_method=False, is_completer=False, to_call=choices_function))
+        set_choices_function(new_arg, choices_function)
     elif choices_method:
-        setattr(new_arg, ATTR_CHOICES_CALLABLE,
-                ChoicesCallable(is_method=True, is_completer=False, to_call=choices_method))
+        set_choices_method(new_arg, choices_method)
     elif completer_function:
-        setattr(new_arg, ATTR_CHOICES_CALLABLE,
-                ChoicesCallable(is_method=False, is_completer=True, to_call=completer_function))
+        set_completer_function(new_arg, completer_function)
     elif completer_method:
-        setattr(new_arg, ATTR_CHOICES_CALLABLE,
-                ChoicesCallable(is_method=True, is_completer=True, to_call=completer_method))
+        set_completer_method(new_arg, completer_method)
 
     setattr(new_arg, ATTR_SUPPRESS_TAB_HINT, suppress_tab_hint)
     setattr(new_arg, ATTR_DESCRIPTIVE_COMPLETION_HEADER, descriptive_header)

help with upgrading autocompletion to 0.9.15 
I am looking into upgrading my code to 0.9.15. The new methods for autocomplete look useful but right now I wonder about
`setattr(load_pcap1, argparse_completer.ACTION_ARG_CHOICES, ('path_complete', ))`
ACTION_ARG_CHOICES seems to have disappeared.
a file has been renamed to argparse_custom too.
Anyway I've tried 
`setattr(load_pcap1, cmd2.argparse_completer.ATTR_CHOICES_CALLABLE, completer_method=cmd2.Cmd.path_complete)`
to no avail
diff --git a/tests/test_argparse_custom.py b/tests/test_argparse_custom.py
index f5d45fd1..99afe2dd 100644
--- a/tests/test_argparse_custom.py
+++ b/tests/test_argparse_custom.py
@@ -40,17 +40,15 @@ def fake_func():
 
 
 @pytest.mark.parametrize('kwargs, is_valid', [
-    ({'choices': []}, True),
     ({'choices_function': fake_func}, True),
     ({'choices_method': fake_func}, True),
     ({'completer_function': fake_func}, True),
     ({'completer_method': fake_func}, True),
-    ({'choices': [], 'choices_function': fake_func}, False),
-    ({'choices': [], 'choices_method': fake_func}, False),
+    ({'choices_function': fake_func, 'choices_method': fake_func}, False),
     ({'choices_method': fake_func, 'completer_function': fake_func}, False),
-    ({'choices_method': fake_func, 'completer_method': fake_func}, False),
+    ({'completer_function': fake_func, 'completer_method': fake_func}, False),
 ])
-def test_apcustom_choices_params_count(kwargs, is_valid):
+def test_apcustom_choices_callable_count(kwargs, is_valid):
     parser = Cmd2ArgumentParser(prog='test')
     try:
         parser.add_argument('name', **kwargs)
@@ -66,11 +64,24 @@ def test_apcustom_choices_params_count(kwargs, is_valid):
     ({'completer_function': fake_func}),
     ({'completer_method': fake_func})
 ])
-def test_apcustom_no_choices_when_nargs_is_0(kwargs):
+def test_apcustom_no_choices_callables_alongside_choices(kwargs):
+    with pytest.raises(TypeError) as excinfo:
+        parser = Cmd2ArgumentParser(prog='test')
+        parser.add_argument('name', choices=['my', 'choices', 'list'], **kwargs)
+    assert 'None of the following parameters can be used alongside a choices parameter' in str(excinfo.value)
+
+
+@pytest.mark.parametrize('kwargs', [
+    ({'choices_function': fake_func}),
+    ({'choices_method': fake_func}),
+    ({'completer_function': fake_func}),
+    ({'completer_method': fake_func})
+])
+def test_apcustom_no_choices_callables_when_nargs_is_0(kwargs):
     with pytest.raises(TypeError) as excinfo:
         parser = Cmd2ArgumentParser(prog='test')
         parser.add_argument('name', action='store_true', **kwargs)
-    assert 'None of the following parameters can be used' in str(excinfo.value)
+    assert 'None of the following parameters can be used on an action that takes no arguments' in str(excinfo.value)
 
 
 def test_apcustom_usage():

pip install -e .[dev]
parse_log_pytest
Pipfile
pytest pytest-cov pytest-mock
apt-get update apt-get install -y gcc
3.7
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
alabaster==0.7.13
attrs==24.2.0
Babel==2.14.0
bleach==6.0.0
certifi @ file:///croot/certifi_1671487769961/work/certifi
cffi==1.15.1
charset-normalizer==3.4.1
-e git+https://github.com/python-cmd2/cmd2.git@4aa8370092d1aba5edaf77bf9a867b23adf4aa97#egg=cmd2
codecov==2.1.13
colorama==0.4.6
coverage==7.2.7
cryptography==44.0.2
distlib==0.3.9
doc8==1.0.0
docutils==0.20.1
exceptiongroup==1.2.2
filelock==3.12.2
flake8==5.0.4
idna==3.10
imagesize==1.4.1
importlib-metadata==4.2.0
iniconfig==2.0.0
invoke==2.2.0
jaraco.classes==3.2.3
jeepney==0.9.0
Jinja2==3.1.6
keyring==23.9.3
livereload==2.7.1
markdown-it-py==2.2.0
MarkupSafe==2.1.5
mccabe==0.7.0
mdurl==0.1.2
more-itertools==9.1.0
packaging==24.0
pbr==6.1.1
pipfile==0.0.2
pkginfo==1.10.0
platformdirs==2.6.2
pluggy==1.2.0
py==1.11.0
pycodestyle==2.9.1
pycparser==2.21
pyflakes==2.5.0
Pygments==2.17.2
pyperclip==1.9.0
pytest==7.4.4
pytest-cov==4.1.0
pytest-mock==3.11.1
pytz==2025.2
readme-renderer==37.3
requests==2.31.0
requests-toolbelt==1.0.0
restructuredtext-lint==1.4.0
rfc3986==2.0.0
rich==13.8.1
SecretStorage==3.3.3
six==1.17.0
snowballstemmer==2.2.0
Sphinx==3.5.3
sphinx-autobuild==2021.3.14
sphinx-rtd-theme==0.5.1
sphinxcontrib-applehelp==1.0.2
sphinxcontrib-devhelp==1.0.2
sphinxcontrib-htmlhelp==2.0.0
sphinxcontrib-jsmath==1.0.1
sphinxcontrib-qthelp==1.0.3
sphinxcontrib-serializinghtml==1.1.5
stevedore==3.5.2
toml @ file:///tmp/build/80754af9/toml_1616166611790/work
tomli==2.0.1
tornado==6.2
tox==3.28.0
twine==4.0.2
typing_extensions==4.7.1
urllib3==2.0.7
virtualenv==20.16.2
wcwidth==0.2.13
webencodings==0.5.1
zipp==3.15.0

name: cmd2
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=2022.12.7=py37h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - 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=22.3.1=py37h06a4308_0
  - pipfile=0.0.2=py_0
  - python=3.7.16=h7a1cb2a_0
  - readline=8.2=h5eee18b_0
  - setuptools=65.6.3=py37h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - toml=0.10.2=pyhd3eb1b0_0
  - wheel=0.38.4=py37h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - alabaster==0.7.13
      - attrs==24.2.0
      - babel==2.14.0
      - bleach==6.0.0
      - cffi==1.15.1
      - charset-normalizer==3.4.1
      - codecov==2.1.13
      - colorama==0.4.6
      - coverage==7.2.7
      - cryptography==44.0.2
      - distlib==0.3.9
      - doc8==1.0.0
      - docutils==0.20.1
      - exceptiongroup==1.2.2
      - filelock==3.12.2
      - flake8==5.0.4
      - idna==3.10
      - imagesize==1.4.1
      - importlib-metadata==4.2.0
      - iniconfig==2.0.0
      - invoke==2.2.0
      - jaraco-classes==3.2.3
      - jeepney==0.9.0
      - jinja2==3.1.6
      - keyring==23.9.3
      - livereload==2.7.1
      - markdown-it-py==2.2.0
      - markupsafe==2.1.5
      - mccabe==0.7.0
      - mdurl==0.1.2
      - more-itertools==9.1.0
      - packaging==24.0
      - pbr==6.1.1
      - pkginfo==1.10.0
      - platformdirs==2.6.2
      - pluggy==1.2.0
      - py==1.11.0
      - pycodestyle==2.9.1
      - pycparser==2.21
      - pyflakes==2.5.0
      - pygments==2.17.2
      - pyperclip==1.9.0
      - pytest==7.4.4
      - pytest-cov==4.1.0
      - pytest-mock==3.11.1
      - pytz==2025.2
      - readme-renderer==37.3
      - requests==2.31.0
      - requests-toolbelt==1.0.0
      - restructuredtext-lint==1.4.0
      - rfc3986==2.0.0
      - rich==13.8.1
      - secretstorage==3.3.3
      - six==1.17.0
      - snowballstemmer==2.2.0
      - sphinx==3.5.3
      - sphinx-autobuild==2021.3.14
      - sphinx-rtd-theme==0.5.1
      - sphinxcontrib-applehelp==1.0.2
      - sphinxcontrib-devhelp==1.0.2
      - sphinxcontrib-htmlhelp==2.0.0
      - sphinxcontrib-jsmath==1.0.1
      - sphinxcontrib-qthelp==1.0.3
      - sphinxcontrib-serializinghtml==1.1.5
      - stevedore==3.5.2
      - tomli==2.0.1
      - tornado==6.2
      - tox==3.28.0
      - twine==4.0.2
      - typing-extensions==4.7.1
      - urllib3==2.0.7
      - virtualenv==20.16.2
      - wcwidth==0.2.13
      - webencodings==0.5.1
      - zipp==3.15.0
prefix: /opt/conda/envs/cmd2

tests/test_argparse_custom.py::test_apcustom_no_choices_callables_alongside_choices[kwargs0] tests/test_argparse_custom.py::test_apcustom_no_choices_callables_alongside_choices[kwargs1] tests/test_argparse_custom.py::test_apcustom_no_choices_callables_alongside_choices[kwargs2] tests/test_argparse_custom.py::test_apcustom_no_choices_callables_alongside_choices[kwargs3] tests/test_argparse_custom.py::test_apcustom_no_choices_callables_when_nargs_is_0[kwargs0] tests/test_argparse_custom.py::test_apcustom_no_choices_callables_when_nargs_is_0[kwargs1] tests/test_argparse_custom.py::test_apcustom_no_choices_callables_when_nargs_is_0[kwargs2] tests/test_argparse_custom.py::test_apcustom_no_choices_callables_when_nargs_is_0[kwargs3]
tests/test_argparse_custom.py::test_apcustom_choices_callable_count[kwargs0-True] tests/test_argparse_custom.py::test_apcustom_choices_callable_count[kwargs1-True] tests/test_argparse_custom.py::test_apcustom_choices_callable_count[kwargs2-True] tests/test_argparse_custom.py::test_apcustom_choices_callable_count[kwargs3-True] tests/test_argparse_custom.py::test_apcustom_choices_callable_count[kwargs4-False] tests/test_argparse_custom.py::test_apcustom_choices_callable_count[kwargs5-False] tests/test_argparse_custom.py::test_apcustom_choices_callable_count[kwargs6-False] tests/test_argparse_custom.py::test_apcustom_usage tests/test_argparse_custom.py::test_apcustom_nargs_help_format tests/test_argparse_custom.py::test_apcustom_nargs_range_validation tests/test_argparse_custom.py::test_apcustom_narg_invalid_tuples[nargs_tuple0] tests/test_argparse_custom.py::test_apcustom_narg_invalid_tuples[nargs_tuple1] tests/test_argparse_custom.py::test_apcustom_narg_invalid_tuples[nargs_tuple2] tests/test_argparse_custom.py::test_apcustom_narg_invalid_tuples[nargs_tuple3] tests/test_argparse_custom.py::test_apcustom_narg_tuple_order tests/test_argparse_custom.py::test_apcustom_narg_tuple_negative tests/test_argparse_custom.py::test_apcustom_narg_tuple_zero_base tests/test_argparse_custom.py::test_apcustom_narg_tuple_one_base tests/test_argparse_custom.py::test_apcustom_narg_tuple_other_ranges tests/test_argparse_custom.py::test_apcustom_print_message tests/test_argparse_custom.py::test_generate_range_error tests/test_argparse_custom.py::test_apcustom_required_options
cmd2/argparse_custom.py CHANGELOG.md
cmd2/argparse_custom.py CHANGELOG.md