Skip to content

Repository files navigation

variants

Documentation Status

variants is a library that provides syntactic sugar for creating alternate forms of functions and other callables, in the same way that alternate constructors are class methods that provide alternate forms of the constructor function.

To create a function with variants, simply decorate the primary form with @variants.primary, which then adds the .variant decorator to the original function, which can be used to register new variants. Here is a simple example of a function that prints text, with variants that specify the source of the text to print:

importvariants@variants.primarydefprint_text(txt):
print(txt)
@print_text.variant('from_file')defprint_text(fobj):
print_text(fobj.read())
@print_text.variant('from_filepath')defprint_text(fpath):
withopen(fpath, 'r') asf:
print_text.from_file(f)
@print_text.variant('from_url')defprint_text(url):
importrequestsr=requests.get(url)
print_text(r.text)

print_text and its variants can be used as such:

print_text('Hello, world!') # Hello, world!# Create a text filewithopen('hello_world.txt', 'w') asf:
f.write('Hello, world (from file)')
# Print from an open file objectwithopen('hello_world.txt', 'r') asf:
print_text.from_file(f) # Hello, world (from file)# Print from the path to a file objectprint_text.from_filepath('hello_world.txt') # Hello, world (from file)# Print from a URLhw_url='https://ganssle.io/files/hello_world.txt'print_text.from_url(hw_url) # Hello, world! (from url)

Differences from singledispatch

While variants and singledispatch are both intended to provide alternative implementations to a primary function, the overall aims are slightly different. singledispatch transparently dispatches to variant functions based on the type of the argument, whereas variants provides explicit alternative forms of the function. Note that in the above example, both print_text.from_filepath and print_text.from_url take a string, one representing a file path and one representing a URL.

Additionally, the variants is compatible with singledispatch, so you can have the best of both worlds; an example that uses both:

@variants.primary@singledispatchdefadd(x, y):
returnx+y@add.variant('from_list')@add.register(list)defadd(x, y):
returnx+ [y]

Which then automatically dispatches between named variants based on type:

>>>add(1, 2)
3>>>add([1], 2)
[1, 2]

But also exposes the explicit variant functions:

>>>add.from_list([1], 2)
[1, 2]
>>>add.from_list()
7 @add.register(list)
8defadd(x, y):
---->9returnx+ [y]
TypeError: unsupportedoperand type(s) for+: 'int'and'list'

It is important to note that the variants decorators must be the outer decorators.

Installation

To install variants, run this command in your terminal:

$ pip install variants

Requirements

This is a library for Python, with support for versions 2.7 and 3.4+.

About

Library providing syntactic sugar for creating variant forms of a canonical function

Resources

Contributing

Stars

74 stars

Watchers

2 watching

Forks

Releases

Packages

Used by

Contributors

Languages