diff --git a/CHANGELOG.md b/CHANGELOG.md
index edc031fa08f555bf3b0dcff7531103efdc48ed9a..e0740ef9ed9814ba6f50dc70d6da3d2552053586 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,5 @@
 # v2.18.4
 
 * added `map_through` to `unpack_dict`
+* added `execute_if_attribute_none`
+* added `execute_if_attribute_not_none`
diff --git a/docs/coding/decorators.rst b/docs/coding/decorators.rst
index e743c13814a3154195e1a870311a7534a6cd4404..52020b492423541999125e7431a576aa3276fbb9 100644
--- a/docs/coding/decorators.rst
+++ b/docs/coding/decorators.rst
@@ -1,6 +1,10 @@
 Decorators
 ==========
 
+.. autofunction:: satella.coding.decorators.execute_if_attribute_none
+
+.. autofunction:: satella.coding.decorators.execute_if_attribute_not_none
+
 .. autofunction:: satella.coding.decorators.transform_result
 
 .. autofunction:: satella.coding.decorators.transform_arguments
diff --git a/satella/__init__.py b/satella/__init__.py
index f9ba0d3c5b94f2c7863d6a95392d13104eba039b..2d29c1ea52f58e3fe8247706a9a0b13c0d800a15 100644
--- a/satella/__init__.py
+++ b/satella/__init__.py
@@ -1 +1 @@
-__version__ = '2.18.4a2'
+__version__ = '2.18.4'
diff --git a/satella/coding/decorators/__init__.py b/satella/coding/decorators/__init__.py
index 5c5784e14a38dfc4aed627e0838887d2649d52c6..3fc063c0f938cee8d73029c01e7754f7d7d9db98 100644
--- a/satella/coding/decorators/__init__.py
+++ b/satella/coding/decorators/__init__.py
@@ -1,6 +1,6 @@
 from .arguments import auto_adapt_to_methods, attach_arguments, for_argument, \
     execute_before, copy_arguments, replace_argument_if, transform_result, \
-    transform_arguments
+    transform_arguments, execute_if_attribute_none, execute_if_attribute_not_none
 from .decorators import wraps, chain_functions, has_keys, short_none, memoize, return_as_list, \
     default_return, cache_memoize, call_method_on_exception
 from .flow_control import loop_while, queue_get
@@ -12,4 +12,5 @@ __all__ = ['retry', 'transform_result', 'transform_arguments',
            'chain_functions', 'has_keys', 'short_none', 'auto_adapt_to_methods',
            'attach_arguments', 'for_argument', 'loop_while', 'memoize',
            'copy_arguments', 'replace_argument_if', 'return_as_list',
-           'default_return', 'cache_memoize', 'call_method_on_exception']
+           'default_return', 'cache_memoize', 'call_method_on_exception',
+           'execute_if_attribute_none', 'execute_if_attribute_not_none']
diff --git a/satella/coding/decorators/arguments.py b/satella/coding/decorators/arguments.py
index e415ed5bbf252e186ba0e3690b075971187e50a4..e7fa1308811e391abd596cff94b292560ddd98de 100644
--- a/satella/coding/decorators/arguments.py
+++ b/satella/coding/decorators/arguments.py
@@ -373,3 +373,40 @@ def for_argument(*t_ops: ForArgumentArg, **t_kwops: ForArgumentArg):
         return inner
 
     return outer
+
+
+def execute_if_attribute_none(attribute: str):
+    """
+    Decorator for instancemethods.
+
+    This will execute the function only if provided attribute is None.
+    Otherwise it will return a None
+
+    :param attribute: name of the attribute to check
+    """
+    def outer(fun):
+        @wraps(fun)
+        def inner(self, *args, **kwargs):
+            if getattr(self, attribute) is None:
+                return fun(self, *args, **kwargs)
+        return inner
+    return outer
+
+
+def execute_if_attribute_not_none(attribute: str):
+    """
+    Decorator for instancemethods.
+
+    This will execute the function only if provided attribute is not None.
+    Otherwise it will return a None
+
+    :param attribute: name of the attribute to check
+    """
+    def outer(fun):
+        @wraps(fun)
+        def inner(self, *args, **kwargs):
+            if getattr(self, attribute) is not None:
+                return fun(self, *args, **kwargs)
+        return inner
+    return outer
+
diff --git a/tests/test_coding/test_decorators.py b/tests/test_coding/test_decorators.py
index 0826265ac6c18b22c835d9c5d0168be29f9c8fb1..425f384fcb756ca0dc63325f391a137a297b2623 100644
--- a/tests/test_coding/test_decorators.py
+++ b/tests/test_coding/test_decorators.py
@@ -9,7 +9,8 @@ from satella.coding import wraps, chain_functions, postcondition, \
 from satella.coding.decorators import auto_adapt_to_methods, attach_arguments, \
     execute_before, loop_while, memoize, copy_arguments, replace_argument_if, \
     retry, return_as_list, default_return, transform_result, transform_arguments, \
-    cache_memoize, call_method_on_exception
+    cache_memoize, call_method_on_exception, execute_if_attribute_none, \
+    execute_if_attribute_not_none
 from satella.coding.predicates import x
 from satella.exceptions import PreconditionError
 
@@ -18,6 +19,42 @@ logger = logging.getLogger(__name__)
 
 class TestDecorators(unittest.TestCase):
 
+    def test_execute_if_attribute_not_none(self):
+        class ExecIfAttrNone:
+            def __init__(self):
+                self.attr = None
+                self.called = 0
+
+            @execute_if_attribute_not_none('attr')
+            def run_me(self):
+                self.called += 1
+
+        e = ExecIfAttrNone()
+        self.assertEqual(e.called, 0)
+        e.run_me()
+        self.assertEqual(e.called, 0)
+        e.attr = 2
+        e.run_me()
+        self.assertEqual(e.called, 1)
+
+    def test_execute_if_attribute_none(self):
+        class ExecIfAttrNone:
+            def __init__(self):
+                self.attr = None
+                self.called = 0
+
+            @execute_if_attribute_none('attr')
+            def run_me(self):
+                self.called += 1
+
+        e = ExecIfAttrNone()
+        self.assertEqual(e.called, 0)
+        e.run_me()
+        self.assertEqual(e.called, 1)
+        e.attr = 2
+        e.run_me()
+        self.assertEqual(e.called, 1)
+
     def test_call_method_on_exception(self):
         a = {'called': False}
         slf = self