new_min_max.py 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. import itertools
  2. from future import utils
  3. if utils.PY2:
  4. from __builtin__ import max as _builtin_max, min as _builtin_min
  5. else:
  6. from builtins import max as _builtin_max, min as _builtin_min
  7. _SENTINEL = object()
  8. def newmin(*args, **kwargs):
  9. return new_min_max(_builtin_min, *args, **kwargs)
  10. def newmax(*args, **kwargs):
  11. return new_min_max(_builtin_max, *args, **kwargs)
  12. def new_min_max(_builtin_func, *args, **kwargs):
  13. """
  14. To support the argument "default" introduced in python 3.4 for min and max
  15. :param _builtin_func: builtin min or builtin max
  16. :param args:
  17. :param kwargs:
  18. :return: returns the min or max based on the arguments passed
  19. """
  20. for key, _ in kwargs.items():
  21. if key not in set(['key', 'default']):
  22. raise TypeError('Illegal argument %s', key)
  23. if len(args) == 0:
  24. raise TypeError
  25. if len(args) != 1 and kwargs.get('default', _SENTINEL) is not _SENTINEL:
  26. raise TypeError
  27. if len(args) == 1:
  28. iterator = iter(args[0])
  29. try:
  30. first = next(iterator)
  31. except StopIteration:
  32. if kwargs.get('default', _SENTINEL) is not _SENTINEL:
  33. return kwargs.get('default')
  34. else:
  35. raise ValueError('{}() arg is an empty sequence'.format(_builtin_func.__name__))
  36. else:
  37. iterator = itertools.chain([first], iterator)
  38. if kwargs.get('key') is not None:
  39. return _builtin_func(iterator, key=kwargs.get('key'))
  40. else:
  41. return _builtin_func(iterator)
  42. if len(args) > 1:
  43. if kwargs.get('key') is not None:
  44. return _builtin_func(args, key=kwargs.get('key'))
  45. else:
  46. return _builtin_func(args)