nyggus / rounder Goto Github PK
View Code? Open in Web Editor NEWPython package for rounding floats and complex numbers in complex Python objects.
License: MIT License
Python package for rounding floats and complex numbers in complex Python objects.
License: MIT License
IntOrFloat
is totally unnecessary, as int
is consistent with float
so can be used wherever float
can be used.
Currently TypeError
is raised, but maybe better to handle this exception?
Create signif
function - move its implementation from Rounder
to this function, and then offer signif
and signif_object
.
In addition, add setuptools
to the dev
dependencies. (Python 3.12 does not come with the built-in installation.)
The type hint for x in signif is IntOrFloat, where that should be Number.
Also, the return type is also Number.
To avoid overlapping with math
and built-in names, change function names to round_object()
and so on.
In order to optimize the performance, it would be better to avoid too many tests in a sequence. Therefore, I do a kind of hierarchical test now.
Note that I also replace lookups like Numbers.number and collections.Mapping by globals as that saves time.
To avoid a test and to make the product more stable. I am now capturing exceptions and if one is raised, I simply return unconverted.
By far not as elegant as the previous version, but it certainly will perform better.
Here it is:
import array
import builtins
import copy
import math
import numbers
from collections.abc import Sequence
from collections.abc import Container
from collections.abc import Set
from collections.abc import Mapping
from collections import deque
from numbers import Number
class UnpickableObjectError(Exception):
pass
class NonNumericTypeError(Exception):
pass
class NonCallableError(Exception):
pass
def _do(func, obj, digits, use_copy):
def convert(obj):
try:
if isinstance(obj, Container):
if isinstance(obj, Sequence):
if isinstance(obj, list):
obj[:] = list(map(convert, obj))
return obj
if isinstance(obj, tuple):
if hasattr(obj, "_fields"):
# it's a collections.namedtuple or a typing.NamedTuple
return obj._replace(**convert(obj._asdict()))
return tuple(convert(list(obj)))
if isinstance(obj, deque):
for i, elem in enumerate(obj):
obj[i] = convert(elem)
return obj
if isinstance(obj, Set):
return type(obj)(convert(list(obj)))
if isinstance(obj, Mapping):
for k, v in obj.items():
obj[k] = convert(obj[k])
return obj
if isinstance(obj, array.array):
obj[:] = array.array(obj.typecode, convert(obj.tolist()))
return obj
if isinstance(obj, Number):
if isinstance(obj, complex):
return convert(obj.real) + convert(obj.imag) * 1j
return func(obj, *digits)
if isinstance(obj, tuple):
# it's a namedtuple
return obj._replace(**convert(obj._asdict()))
# try as a class instance
convert(obj.__dict__)
return obj
except Exception:
pass
return obj
if use_copy:
try:
obj = copy.deepcopy(obj)
except TypeError:
raise UnpickableObjectError()
return convert(obj)
I would prefer the following code to convert a dict (more compact, no explicit loops):
if isinstance(value, dict):
value.update({k, convert(v)})
return value
I have implemented dedicated handlng for collections.deque
objects.
In order for collections.Counter
to work, I have changed the code for dict
handling.
And I have verified that collections.defaultdict
, collections.UserDict
and collections.UserList
work as expected.
Here's the updated code (including the support dor namedtuples):
def convert(obj):
if isinstance(obj, complex):
# this has to be checked before the Number check,
# as complex is a Number
return convert(obj.real) + convert(obj.imag) * 1j
if isinstance(obj, numbers.Number):
return func(obj, *digits)
if isinstance(obj, list):
obj[:] = list(map(convert, obj))
return obj
if isinstance(obj, tuple):
if hasattr(obj, "_fields"): # it's a namedtuple
return obj._replace(**convert(obj._asdict()))
else:
return tuple(convert(list(obj)))
if isinstance(obj, set):
return set(convert(list(obj)))
if isinstance(obj, frozenset):
return frozenset(convert(list(obj)))
if isinstance(obj, (dict, collections.OrderedDict)):
for k, v in obj.items():
obj[k] = convert(obj[k])
return obj
if isinstance(obj, array.array):
obj[:] = array.array(obj.typecode, convert(obj.tolist()))
return obj
if isinstance(obj, collections.deque):
for i, elem in enumerate(obj):
obj[i] = convert(elem)
return obj
if hasattr(obj, "__dict__"):
convert(obj.__dict__)
return obj
return obj
Currently a TypeError
is returned when rounder
objects are fed in with instances of these two types:
TypeError: __new__() missing 1 required positional argument: ...
Checking for both can be done as
isinstance(my_named_tuple, tuple) and hasattr(my_named_tuple, "_fields")
It would be nice if we could also change the attributes of a class instance.
This extra code (at the bottom of convert) should do:
if hasattr(value, "__dict__"):
convert(value.__dict__)
return value
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.