All Projects → mikeckennedy → Python Switch

mikeckennedy / Python Switch

Licence: mit
Adds switch blocks to Python

Programming Languages

python
139335 projects - #7 most used programming language
python3
1442 projects
language
365 projects

Labels

Projects that are alternatives of or similar to Python Switch

Raspberry Pi Safe Off Switch
A set of scripts that can be used to provide a "safe power off switch" for a Raspberry Pi.
Stars: ✭ 144 (-38.2%)
Mutual labels:  switch
Flutter smart select
SmartSelect allows you to easily convert your usual form select or dropdown into dynamic page, popup dialog, or sliding bottom sheet with various choices input such as radio, checkbox, switch, chips, or even custom input. Supports single and multiple choice.
Stars: ✭ 179 (-23.18%)
Mutual labels:  switch
Nro2nsp
Build Redirction and romfs nsps out of .nros
Stars: ✭ 205 (-12.02%)
Mutual labels:  switch
Ghidra Switch Loader
Nintendo Switch loader for Ghidra
Stars: ✭ 146 (-37.34%)
Mutual labels:  switch
React Icheck
🔘 iCheck components built with React. Highly customizable checkbox, radio buttons and radio group.
Stars: ✭ 175 (-24.89%)
Mutual labels:  switch
Easybutton
Arduino library for debouncing momentary contact switches, detect press, release, long press and sequences with event definitions and callbacks.
Stars: ✭ 187 (-19.74%)
Mutual labels:  switch
Panelswitchhelper
✔️ A framework that helps the keyboard smoothly transition to the function panel 一个帮助键盘平稳过渡到功能面板的框架,支持动画无缝衔接,支持 activity/fragment/dialog/dialogFragment/popupWindow 容器,支持IM/直播/视频播放/信息流评论等场景,支持全屏模式。
Stars: ✭ 1,957 (+739.91%)
Mutual labels:  switch
Yuzu
Nintendo Switch Emulator
Stars: ✭ 17,405 (+7369.96%)
Mutual labels:  switch
React Native Switch
Customisable switch component for RN
Stars: ✭ 179 (-23.18%)
Mutual labels:  switch
Tristatetogglebutton
Customizable tri-state toggle button (with three states, three state toggle) for Android
Stars: ✭ 198 (-15.02%)
Mutual labels:  switch
Goldleaf
🍂 Multipurpose homebrew tool for Nintendo Switch
Stars: ✭ 2,026 (+769.53%)
Mutual labels:  switch
Plutonium
An easy-to-use UI framework for Nintendo Switch homebrew
Stars: ✭ 166 (-28.76%)
Mutual labels:  switch
Ha Wyzeapi
Home Assistant Integration for Wyze Bulbs, Switches, Sensors and Lock
Stars: ✭ 187 (-19.74%)
Mutual labels:  switch
Windowwalker
Keyboard Alternative to Alt-Tab on Windows
Stars: ✭ 145 (-37.77%)
Mutual labels:  switch
Android Switchicon
Google launcher-style implementation of switch (enable/disable) icon
Stars: ✭ 2,337 (+903%)
Mutual labels:  switch
Pm
The easy way to switch between your projects on ZSH
Stars: ✭ 142 (-39.06%)
Mutual labels:  switch
Centos2ol
Script and documentation to switch CentOS Linux to Oracle Linux
Stars: ✭ 181 (-22.32%)
Mutual labels:  switch
Mechvibes
Mechvibes
Stars: ✭ 226 (-3%)
Mutual labels:  switch
Keymapper
📱 An Android app that maps any keys to actions.
Stars: ✭ 207 (-11.16%)
Mutual labels:  switch
Kosmos
All-in-One CFW Package for the Nintendo Switch - previously SDFilesSwitch
Stars: ✭ 2,157 (+825.75%)
Mutual labels:  switch

switchlang

Adds switch blocks to the Python language.

This module adds explicit switch functionality to Python without changing the language. It builds upon a standard way to define execution blocks: the with statement.

Example

from switchlang import switch

def main():
    num = 7
    val = input("Enter a character, a, b, c or any other: ")

    with switch(val) as s:
        s.case('a', process_a)
        s.case('b', lambda: process_with_data(val, num, 'other values still'))
        s.default(process_any)
    
def process_a():
    print("Found A!")
    
def process_any():
    print("Found Default!")
    
def process_with_data(*value):
    print("Found with data: {}".format(value))

main()

Installation

Simply install via pip:

pip install switchlang

Features

  • More explicit than using dictionaries with functions as values.
  • Verifies the signatures of the methods
  • Supports default case
  • Checks for duplicate keys / cases
  • Keys can be anything hashable (numbers, strings, objects, etc.)
  • Could be extended for "fall-through" cases (doesn't yet)
  • Use range and list for multiple cases mapped to a single action

Multiple cases, one action

You can map ranges and lists of cases to a single action as follows:

# with lists:
value = 4  # matches even number case

with switch(value) as s:
    s.case([1, 3, 5, 7], lambda: ...)
    s.case([0, 2, 4, 6, 8], lambda: ...)
    s.default(lambda: ...)
# with ranges:
value = 4  # matches first case

with switch(value) as s:
    s.case(range(1, 6), lambda: ...)
    s.case(range(6, 10), lambda: ...)
    s.default(lambda: ...)

Closed vs. Open ranges

Looking at the above code it's a bit weird that 6 appears at the end of one case, beginning of the next. But range() is half open/closed.

To handle the inclusive case, I've added closed_range(start, stop). For example, closed_range(1,5) -> [1,2,3,4,5]

Why not just raw dict?

The biggest push back on this idea is that we already have this problem solved. You write the following code.

switch = {
    1: method_on_one,
    2: method_on_two,
    3: method_three
}

result = switch.get(value, default_method_to_run)()

This works but is very low on the functionality level. We have a better solution here I believe. Let's take this example and see how it looks in python-switch vs raw dicts:

# with python-switch:

while True:
    action = get_action(action)

    with switch(action) as s:
        s.case(['c', 'a'], create_account)
        s.case('l', log_into_account)
        s.case('r', register_cage)
        s.case('u', update_availability)
        s.case(['v', 'b'], view_bookings)
        s.case('x', exit_app)
        s.case('', lambda: None)
        s.case(range(1,6), lambda: set_level(action))
        s.default(unknown_command)
    
    print('Result is {}'.format(s.result))

Now compare that to the espoused pythonic way:

# with raw dicts

while True:
    action = get_action(action)

    switch = {
        'c': create_account,
        'a': create_account,
        'l': log_into_account,
        'r': register_cage,
        'u': update_availability,
        'v': view_bookings,
        'b': view_bookings,
        'x': exit_app,
        1: lambda: set_level(action),
        2: lambda: set_level(action),
        3: lambda: set_level(action),
        4: lambda: set_level(action),
        5: lambda: set_level(action),
        '': lambda: None,
    }
    result = switch.get(action, unknown_command)()
    print('Result is {}'.format(result))

Personally, I much prefer to read and write the one above. That's why I wrote this module. It seems to convey the intent of switch way more than the dict. But either are options.

Why not just if / elif / else?

The another push back on this idea is that we already have this problem solved. Switch statements are really if / elif / else blocks. So you write the following code.

# with if / elif / else

while True:
    action = get_action(action)

    if action == 'c' or action == 'a':
        result = create_account()
    elif action == 'l':
        result = log_into_account()
    elif action == 'r':
        result = register_cage()
    elif action == 'a':
        result = update_availability()
    elif action == 'v' or action == 'b':
        result = view_bookings()
    elif action == 'x':
        result = exit_app()
    elif action in {1, 2, 3, 4, 5}:
        result = set_level(action)
    else:
        unknown_command()
        
    print('Result is {}'.format(result))

I actually believe this is a little better than the raw dict option. But there are still things that are harder.

  • How would you deal with fall-through cleanly?
  • Did you notice the bug? We forgot to set result in default case (else) and will result in a runtime error (but only if that case hits).
  • There is another bug. Update update_availability will never run because it's command (a) is bound to two cases. This is guarded against in switch and you would receive a duplicate case error the first time it runs at all.
  • While it's pretty clear, it's much more verbose and less declarative than the switch version.

Again, compare the if / elif / else to what you have with switch. This code is identical except doesn't have the default case bug.

while True:
    action = get_action(action)

    with switch(action) as s:
        s.case(['c', 'a'], create_account)
        s.case('l', log_into_account)
        s.case('r', register_cage)
        s.case('u', update_availability)
        s.case(['v', 'b'], view_bookings)
        s.case('x', exit_app)
        s.case('', lambda: None)
        s.case(range(1,6), lambda: set_level(action))
        s.default(unknown_command)
    
    print('Result is {}'.format(s.result))
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].