Skip to main content
edited title
Link
Heslacher
  • 51k
  • 5
  • 83
  • 177

C-style `switch` statement implementation in Python using decorators

Tweeted twitter.com/StackCodeReview/status/1199432799075389440
deleted 8 characters in body
Source Link
Tobi Alafin
  • 1.8k
  • 1
  • 15
  • 32

 
I don't think I qualify as a beginner anymore (I'm hopinglooking to transition into a morestart getting paid to write Python heavy role at worksoon), and I would appreciate guidance on best practices.

 
I don't think I qualify as a beginner anymore (I'm hoping to transition into a more Python heavy role at work), and I would appreciate guidance on best practices.

 
I don't think I qualify as a beginner anymore (I'm looking to start getting paid to write Python soon), and I would appreciate guidance on best practices.

All Those Capitals Are Really Unnecessary
Source Link
Mast
  • 13.9k
  • 12
  • 57
  • 128

C-style `switch` Statement Implementationstatement implementation in Python Using Decoratorsusing decorators

"""Module to implement C style switch functionality using decorators.

  Functions:
    `switch_construct`: Returns functions that provide the required functionality and provides a closure for said functions.
"""

__all__ = ["switch", "case", "break_"]

import operator as op

def switch_construct():
  """Forms a closure to store the meta data used by the switch construct.
    
    Vars:
      `closure` (list): List to store dictionaries containing metadata for each `switch` instance.
        * The dictionary contains two keys: "control" and "halt".
          - "control": the value governing the current switch instance. `case` blocks are tested against this value.
          - `halt`: value is used to implement break functionality. 
            > `True`: break after execution of current function.
            > Default: `False`.

    Returns:
      tuple: A tuple of functions (`switch`, `case`, `break_`) defined in the function's scope.
  """
  closure = []

  def switch(input_):
    """Sets the metadata for the current `switch` block.
      
      Args:
        `input` (object): The value governing the switch construct.

      Returns:
        `function`: A decorator for the function enclosing the switch block.
    """
    nonlocal closure
    def decorator(func):
      closure.append({"control": input_, "halt": False})  # Add the metadata to closure.
      # Sets `control` to `input_` and `halt` to `False` for each `switch` block.
      def wrapper(*args, **kwargs):
        return func(*args, **kwargs)
      wrapper.switch_index = len(closure)-1 
      # Assign the `switch_index` attribute to the decorated function for using when retrieving switch construct metadata.
      return wrapper
    return decorator

  def case(value, enclosing, test = op.eq):
    """Returns a decorator which executes decorated function only if its `value` argument satisfies some test.
      
      Args:
        `value` (object): value used to test whether the decorated function should be executed.
        `enclosing` (function): enclosing function corresponding to the current switch block.
        `test` (function): test that should be satisfied before decorated function is executed.
          - Default value is `op.eq`.
          - Returns `bool`.

      Returns:
        function: A decorator for the function corresponding to the case block.
    """
    def decorator(func):
      nonlocal closure
      index = enclosing.switch_index
      return_value = None
      if test(value, closure[index]["control"]) and not closure[index]["halt"]:
        return_value = func()
      return return_value
    return decorator

  def break_(enclosing):
    """Used to indicate that the switch construct should break after execution of the current function."""
    nonlocal closure
    closure[enclosing.switch_index]["halt"] = True
    return None

  return case, switch, break_


case, switch, break_ = switch_construct()
  
@switch(2)
def func():
  """Sample use case of the switch construct."""
  @case(1, func)
  def _(num=10):
    print(num + 1)

  @case(2, func)
  def _(num=10):
    print(num + 2)
    break_(func)

  @case(3, func, op.gt)
  def _(num=10):
    print(num + 3)

func()
```

C-style `switch` Statement Implementation in Python Using Decorators

"""Module to implement C style switch functionality using decorators.

  Functions:
    `switch_construct`: Returns functions that provide the required functionality and provides a closure for said functions.
"""

__all__ = ["switch", "case", "break_"]

import operator as op

def switch_construct():
  """Forms a closure to store the meta data used by the switch construct.
    
    Vars:
      `closure` (list): List to store dictionaries containing metadata for each `switch` instance.
        * The dictionary contains two keys: "control" and "halt".
          - "control": the value governing the current switch instance. `case` blocks are tested against this value.
          - `halt`: value is used to implement break functionality. 
            > `True`: break after execution of current function.
            > Default: `False`.

    Returns:
      tuple: A tuple of functions (`switch`, `case`, `break_`) defined in the function's scope.
  """
  closure = []

  def switch(input_):
    """Sets the metadata for the current `switch` block.
      
      Args:
        `input` (object): The value governing the switch construct.

      Returns:
        `function`: A decorator for the function enclosing the switch block.
    """
    nonlocal closure
    def decorator(func):
      closure.append({"control": input_, "halt": False})  # Add the metadata to closure.
      # Sets `control` to `input_` and `halt` to `False` for each `switch` block.
      def wrapper(*args, **kwargs):
        return func(*args, **kwargs)
      wrapper.switch_index = len(closure)-1 
      # Assign the `switch_index` attribute to the decorated function for using when retrieving switch construct metadata.
      return wrapper
    return decorator

  def case(value, enclosing, test = op.eq):
    """Returns a decorator which executes decorated function only if its `value` argument satisfies some test.
      
      Args:
        `value` (object): value used to test whether the decorated function should be executed.
        `enclosing` (function): enclosing function corresponding to the current switch block.
        `test` (function): test that should be satisfied before decorated function is executed.
          - Default value is `op.eq`.
          - Returns `bool`.

      Returns:
        function: A decorator for the function corresponding to the case block.
    """
    def decorator(func):
      nonlocal closure
      index = enclosing.switch_index
      return_value = None
      if test(value, closure[index]["control"]) and not closure[index]["halt"]:
        return_value = func()
      return return_value
    return decorator

  def break_(enclosing):
    """Used to indicate that the switch construct should break after execution of the current function."""
    nonlocal closure
    closure[enclosing.switch_index]["halt"] = True
    return None

  return case, switch, break_


case, switch, break_ = switch_construct()
  
@switch(2)
def func():
  """Sample use case of the switch construct."""
  @case(1, func)
  def _(num=10):
    print(num + 1)

  @case(2, func)
  def _(num=10):
    print(num + 2)
    break_(func)

  @case(3, func, op.gt)
  def _(num=10):
    print(num + 3)

func()
```

C-style `switch` statement implementation in Python using decorators

"""Module to implement C style switch functionality using decorators.

  Functions:
    `switch_construct`: Returns functions that provide the required functionality and provides a closure for said functions.
"""

__all__ = ["switch", "case", "break_"]

import operator as op

def switch_construct():
  """Forms a closure to store the meta data used by the switch construct.
    
    Vars:
      `closure` (list): List to store dictionaries containing metadata for each `switch` instance.
        * The dictionary contains two keys: "control" and "halt".
          - "control": the value governing the current switch instance. `case` blocks are tested against this value.
          - `halt`: value is used to implement break functionality. 
            > `True`: break after execution of current function.
            > Default: `False`.

    Returns:
      tuple: A tuple of functions (`switch`, `case`, `break_`) defined in the function's scope.
  """
  closure = []

  def switch(input_):
    """Sets the metadata for the current `switch` block.
      
      Args:
        `input` (object): The value governing the switch construct.

      Returns:
        `function`: A decorator for the function enclosing the switch block.
    """
    nonlocal closure
    def decorator(func):
      closure.append({"control": input_, "halt": False})  # Add the metadata to closure.
      # Sets `control` to `input_` and `halt` to `False` for each `switch` block.
      def wrapper(*args, **kwargs):
        return func(*args, **kwargs)
      wrapper.switch_index = len(closure)-1 
      # Assign the `switch_index` attribute to the decorated function for using when retrieving switch construct metadata.
      return wrapper
    return decorator

  def case(value, enclosing, test = op.eq):
    """Returns a decorator which executes decorated function only if its `value` argument satisfies some test.
      
      Args:
        `value` (object): value used to test whether the decorated function should be executed.
        `enclosing` (function): enclosing function corresponding to the current switch block.
        `test` (function): test that should be satisfied before decorated function is executed.
          - Default value is `op.eq`.
          - Returns `bool`.

      Returns:
        function: A decorator for the function corresponding to the case block.
    """
    def decorator(func):
      nonlocal closure
      index = enclosing.switch_index
      return_value = None
      if test(value, closure[index]["control"]) and not closure[index]["halt"]:
        return_value = func()
      return return_value
    return decorator

  def break_(enclosing):
    """Used to indicate that the switch construct should break after execution of the current function."""
    nonlocal closure
    closure[enclosing.switch_index]["halt"] = True
    return None

  return case, switch, break_


case, switch, break_ = switch_construct()
  
@switch(2)
def func():
  """Sample use case of the switch construct."""
  @case(1, func)
  def _(num=10):
    print(num + 1)

  @case(2, func)
  def _(num=10):
    print(num + 2)
    break_(func)

  @case(3, func, op.gt)
  def _(num=10):
    print(num + 3)

func()
Source Link
Tobi Alafin
  • 1.8k
  • 1
  • 15
  • 32
Loading