Skip to main content

Python functions and classes that make python even easier than it is!

Project description

izy

Python functions and classes that make python even easier than it is! You will wonder why these are not already built-in in python! :)

The sooner you pip install izy, the less time you waste! Just 3 keystrokes to install and import :)

pip install izy

Now that you have it, here are the functionlities:

Sorting

Some operations like argsort need 1 or 2 lines to implement in python, but the code is not pythonically readable as it should be. Some other functions like topk are somehow hidden in the built-in modules, which we expose with ease!

Let us have a big list of numbers and give it an izy try:

>>> from izy import *
>>> mylist = [4.2, 10, -8, 0, 4, 33, 6, 97, 1, 6., 41, -6, 0.0]

>>> topk(mylist, 4)
[97, 41, 33, 10]

>> topk(mylist, -3)     # as you would expect
[-8, -6, 0]             

>>> argmax(mylist)      # not to mention argmin
7

>>> argsort(mylist)
[2, 11, 3, 12, 8, 4, 0, 6, 9, 1, 5, 10, 7]

>>> argsort(mylist, reverse=True)
[7, 10, 5, 1, 6, 9, 0, 4, 8, 3, 12, 11, 2]

>>> descending(mylist)   # I like it more than sorted(x, reverse=True)
[97, 41, 33, 10, 6, 6.0, 4.2, 4, 1, 0, 0.0, -6, -8]

>>> reorder(mylist, argsort(mylist))    # like numpy array indexing
[-8, -6, 0, 0.0, 1, 4, 4.2, 6, 6.0, 10, 33, 41, 97]

If you have a dict (or more precisely a Mapping), the arg* functions take keys as indices:

>>> mydict = {'a': 1, 'b': 4, 'c': -1}

>>> argmin(mydict)
'c'

>>> reorder(mydict, argsort(mydict))    # sorry it cannot return a sorted dict :) 
[-1, 1, 4]                              # maybe an OrderedDict in the future...

Scorer

Dict subclass for scoring hashable items. Generalizes functionality of built-in Counter to floating-point numbers with full math operation support.

>>> from izy import Scorer
>>> s1 = Scorer({'a': 1, 'b': 2, 'c': 5})
>>> s1['d'] = 3
>>> s1
Scorer({c: 5, d: 3, b: 2, a: 1})

>>> s2 = Scorer('abc', [-2, 3, 4])
>>> s2
Scorer({c: 4, b: 3, a: -2})

Mathematical operators (+, -, *, /, //, %, **) are supported for both Scorer and scalar right-hand operands.

>>> s1 + s2         
Scorer({c: 9, b: 5, d: 3, a: -1})  

>>> s1 / 4
Scorer({c: 1.25, d: 0.75, b: 0.5, a: 0.25})

WARNING! To support partial update with math operations, we carry non-common items from the first operand unchanged, but those from the second operand are ignored.

Unary math operators (+, -) are available too.

>>> +s2             # special usage for useless uniary `+` (only keeps positive itmes)
Scorer({c: 4, b: 3})

>>> s1 + (+s2)      # not equivalent to s1 + s2
Scorer({c: 9, b: 5, d: 3, a: 1})

We also have abs(), round():

>>> abs(s2) 
Scorer({c: 4, b: 3, a: 2})

Logical operators &, | apply element-wise min/max and they are also applicable to scalars. As Scorer is not a set or even multiset (like Counter), we don't refer to these as intersection and union, but the functionalities are still similar.

>>> s1 & s2         # ~ min (drops non-common items)
Scorer({c: 4, b: 2, a: -2})

>>> s1 & 2          # drops items with score less than 2
Scorer({c: 5, d: 3, b: 2})

>>> s1 | s2         # ~ max
Scorer({c: 5, b: 3, d: 3, a: 1})

About the above warning, note that (s1 | (s1 & s2)) gives the subset of s1 which also exists in s2. You can use this to force math operations to return common items only.

And finally the ultimate goal of the Scorer is to sort its items according to scores and give us the best, topk (or worst, bottomk).

>>> s1.best()           
('c', 5)

>>> s1.topk(3)          # alias to `s1.best` but more readable when you specify the number of items
[('c', 5), ('d', 3), ('b', 2)]

>>> s1.topk(-2)         # negative k means bottom k
[('a', 1), ('b', 2)]

>>> s1.ascending()      # prefer this to `best` or `topk` with special values of n or k (None, 0, inf)
[('a', 1), ('b', 2), ('d', 3), ('c', 5)]

>>> s1.median()         # if scorer length is even, lower median is returned
('b', 2)

Decorators

Python functools is really interesting, but it really lacks some generally usefull decorators.

First, @returns() and @yields() make your function/generator return/yield namedtuples to more pythonically access your function output. It also looks like an easy documentation to me (about the meaning of what function returns and not just the type).

@returns('x', 'plus_one')
def myfunction(x):
    return x, x+1

@yields('a', 'a_doubled')
def mygenerator(x):
    for i in range(x):
        yield {'a':i, 'a_doubled': i*2}

n = myfunction(5).plus_one

@returns_time() calculates function runtime and returns it as a datetime.timedelta object. You can change time format to milis (int) or seconds (float). It returns a namedtuple which you can rename using @returns.

@returns_time()
def timed(x):
    z = 0
    for i in range(x * 1000000):
        z += i

@returns('output', 'milis')
@returns_time(milis=True)
def timed_milis(x):
    z = 0
    for i in range(x * 1000000):
        z += i
    return 'done'

>>> timed(64)
timed_output(output=None, time=datetime.timedelta(seconds=2, microseconds=530048))

>>> timed_milis(32)
timed_milis_output(output='done', milis=1289)

@logs() does what it says at three stages: before calling, after returning and on exceptions. You can control log level for each stage, log to_file using default logger (named after the function) or pass your own logging.Logger.

@logs(before=logging.DEBUG, after=logging.INFO, to_file='logged.log')
def logged(x, **kw):
    for i in range(1000000):
        x += i

>>> logged(1, key1=5, key2=7.2)

[2021-12-31 08:56:33][logged][DEBUG] - Function `logged` called with args: (4, key1=5, key2=7.2)
[2021-12-31 08:56:33][logged][INFO] - Function `logged` returned after 0:00:00.029084 with result: None

@fix_this() reminds you to fix something in stronger way than a passive comment. It raises UserWarning at runtime and does this everytime :)

@fix_this('It always prints ValueError, errors should be raised!')
def please(x):
    print('ValueError')

This one @ignores() given exceptions (and returns None). Who knows when and why you need this? :) You can stack it on top of @logs() to be aware of ignored exceptions.

@ignores(ValueError, IndexError)
@logs()
def ignorer(x):
    for i in range(x):
        raise ValueError

Want more useful exception handler? @fallsback() falls back on specified exception to predefined return value or another callable. For multiple exceptions, stack it like this:

@fallsback(ZeroDivisionError, 1)
@fallsback(ValueError, lambda x: x**2)
def multifall2callable(x):
    if x < 0:
        raise ValueError
    else:
        raise ZeroDivisionError

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

izy-0.1.2.tar.gz (13.4 kB view details)

Uploaded Source

Built Distribution

izy-0.1.2-py3-none-any.whl (11.0 kB view details)

Uploaded Python 3

File details

Details for the file izy-0.1.2.tar.gz.

File metadata

  • Download URL: izy-0.1.2.tar.gz
  • Upload date:
  • Size: 13.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.7.1 importlib_metadata/4.10.0 pkginfo/1.8.2 requests/2.26.0 requests-toolbelt/0.9.1 tqdm/4.62.3 CPython/3.9.7

File hashes

Hashes for izy-0.1.2.tar.gz
Algorithm Hash digest
SHA256 8dedb812f6d0d384c7e47f7af1cb1b61b05febb1d3905ddbfb7194401164abb5
MD5 67f5a6ebf1a4a4ef67c3e66614146343
BLAKE2b-256 e827f7541fb039e0fb8b32fb45f8939edd919c5300dcbd1a25bc21b8a55e49aa

See more details on using hashes here.

File details

Details for the file izy-0.1.2-py3-none-any.whl.

File metadata

  • Download URL: izy-0.1.2-py3-none-any.whl
  • Upload date:
  • Size: 11.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.7.1 importlib_metadata/4.10.0 pkginfo/1.8.2 requests/2.26.0 requests-toolbelt/0.9.1 tqdm/4.62.3 CPython/3.9.7

File hashes

Hashes for izy-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 ff59f6a19c76599e7218b8c2ec0d2316694246ccc37d52c61571f855b8c71307
MD5 f3ec3d36329cb0d876250b3436e9c1d7
BLAKE2b-256 0eb84876d390b63d7823c5ff57a2e5abd7972393e139a40c8a6c4344c95ad867

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page