jab / bidict Goto Github PK
View Code? Open in Web Editor NEWThe bidirectional mapping library for Python.
Home Page: https://bidict.readthedocs.io
License: Mozilla Public License 2.0
The bidirectional mapping library for Python.
Home Page: https://bidict.readthedocs.io
License: Mozilla Public License 2.0
The PyPi homepage is given as the Read the Docs site and many legal types will not go beyond that in looking for the software licence so I would suggest including the licence on that page.
Apologies for the slightly cheeky issue, but I'm currently trying to gather a list of endorsements from people using Hypothesis and was hoping that as the maintainer of an open source project you'd be willing to put your name down there. :-)
https://github.com/jab/bidict/blob/master/bidict.py#L426 - unless I miss something this looks like a unnecessary line. After doing self._fwd = self._bwd
you are assiging self._fwd
(which already has the value of self._bwd
) back to self._bwd
.
Any reason for doing this?
import copy
from bidict import bidict
d = bidict({0: 1, 2: 3})
d2 = copy.deepcopy(d)
x = d2.inv.inv
This raises:
~/Library/...
169 def inv(self):
170 """Alias for :attr:`inverse`."""
--> 171 return self.inverse
172
173 def __getstate__(self):
~/Library/...
159 return self._inv
160 # Otherwise a weakref is stored in self._invweak. Try to get a strong ref from it.
--> 161 inv = self._invweak()
162 if inv is not None:
163 return inv
AttributeError: _invweak
In addition, this also raises the same error:
import pickle
from bidict import bidict
d = bidict({0: 1, 2: 3})
pickle.loads(pickle.dumps(d)).inv.inv
To enable me to focus better on more core functionality, I'm considering removing namedbidict. The value it has provided doesn't seem worth the maintenance burden.
Here is a sample of people/orgs whose code would break if this happens:
Everyone please give feedback here, and please spread the word to other bidict users. I'm leaning toward going through with this, but if users' feedback trumps the rationale above, I won't.
Importing bidict causes the tfp.sts.Autoregressive class to not work at all. Simplest code to reproduce the problem is as follows
Not sure if the issue is with tfp or bidict.
import bidict
import tensorflow_probability as tfp
a=tfp.sts.Autoregressive(order=2)
AttributeError: 'LinearOperatorDiag' object has not attribute 'keys'
bidict :0.19.0
tf : 2.2.0
tfp:0.10.0
see tensorflow/probability#1016
Would a pull request be considered that would make the inverse dict a defaultdict(list) therefore allowing that same functionality as a regular map? Removing the duplicate checks would also speed up bidict.
Hi Jab, thank you for this great package.
I recently upgraded my bidict to version 11.0 from an older version (bidict==0.9.0.post1), and all of my tests broke.
It seems like the syntax bd[:some_key] is not working anymore.
>>> import bidict
>>> bd = bidict.bidict()
>>> bd["hello"] = "world"
>>> bd[:"world"]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/real/.virtualenvs/wchat/lib/python3.4/site-packages/bidict/_common.py", line 57, in __getitem__
return self._fwd[key]
TypeError: unhashable type: 'slice'
Is this behaviour intentional? I just checked at the docs and it seems like any mention of this syntax is gone.
Hi,
I would like to kindly ask if you can push all missing git tags to the corresponding pypi releases to github and also keep git tags in sync in the future?
This would really make it easier to map specific pypi releases to exact commits in the git tree in an easy and convenient way.
Also it would aid in subscribing to github release watch notifications etc.
cheers 🐱
Hi, we are using version bidict==0.18.0 and CPython 2.7.13 and got the following error here:
bidict/_abc.py in subclasshook at line 90
def __subclasshook__(cls, C): # noqa: N803 (argument name should be lowercase)
"""Check if *C* is a :class:`~collections.abc.Mapping`
that also provides an ``inverse`` attribute,
thus conforming to the :class:`BidirectionalMapping` interface,
in which case it will be considered a (virtual) C
even if it doesn't explicitly extend it.
"""
that also provides an ``inverse`` attribute,
thus conforming to the :class:`BidirectionalMapping` interface,
in which case it will be considered a (virtual) C
even if it doesn't explicitly extend it.
"""
if cls is not BidirectionalMapping: # lgtm [py/comparison-using-is] # global name 'BidirectionalMapping' is not defined here
return NotImplemented
if not Mapping.__subclasshook__(C):
return NotImplemented
mro = getattr(C, '__mro__', None)
if mro is None: # Python 2 old-style class
...
C is a <type 'unicode'> here. So we simply pass unicode string to logger and such error raised. Looks like this happened because of the following line in python2.7/logging/init.py:
if (args and len(args) == 1 and isinstance(args[0], collections.Mapping)
Could anybody help with this issue? What we are doing wrong? Thanks in advance.
a={
2:(3,4),
5:3
}
a_inv={
3:(2,5),
4:2,
}
Is it possible to achieve using bidict?
Hi All,
I came across bidict
while searching for a more general application of the functionality in this helpful repo. I was wondering if anyone here can point me towards the data structure I'm looking for or help me expand on bidict
to build it.
The data structure I'm looking for can, in O(1)
time, go from an element of a collection to getting the rest of the elements in that collection. If the collections are of size 2, this boils down to what bidict
does now. In the case where they're not, like
collection = [
[1, 'hola', 'hello'],
[2, 'audios', 'goodbye'],
]
I'm hoping to index like collection['goodbye']
and get [2, 'audios', 'goodbye']
. The inclusion of the key used to index in the return structure doesn't matter to me.
Questions:
O(1)
indexing constraint relevent?bidict
be easily expanded to do this?Solutions:
O(n)
process.bidict
does, but with the added constraint that all the elements are unique. My understanding is that bidict
currently only requires that all the keys are unique and that all the values are unique. Can someone validate this? If true, is that why bidict
doesn't currently take this approach?Use Case
The real world use case is to avoid making a database call to get simple, unchanging information out of a relational database table. For example, we might store permission levels in an application DB as integers but refer to them in API responses and errors different strings. All elements of the collection relate to the same idea, they're just different representations. One alternative to having a structure like this is to have lots of translation functions. Ex: def db_int_to_API_representation(db_int):
. However, as the number of entries in the collections grows, the number of functions needed could grow as its factorial. A more realistic example collection is:
permissions = [
[1, 'readOnly', 'read_only', 'READ'],
[2, 'writeOnly', 'write_only', 'WRITE'],
[3, 'readWrite', 'read_write', 'READWRITE'],
]
Currently a bidict and its inverse maintain strong references to one another and one another's _fwd and _bwd dicts. Use weakref?
Currently if you want to check whether a bidict contains the mapping (k, v), you have to write b.get(k) == v
(or b.get(k, sentinel) == v
when v is None).
Terry Reedy proposes also allowing b[k:v]
to return True or False to perform this check.
caffe@CVML:~$ sudo pip install bidict
[sudo] password for caffe:
The directory '/home/caffe/.cache/pip/http' or its parent directory is not owned by the current user and the cache has been disabled. Please check the permissions and owner of that directory. If executing pip with sudo, you may want sudo's -H flag.
The directory '/home/caffe/.cache/pip' or its parent directory is not owned by the current user and caching wheels has been disabled. check the permissions and owner of that directory. If executing pip with sudo, you may want sudo's -H flag.
Looking in indexes: http://mirrors.aliyun.com/pypi/simple/
Collecting bidict
Downloading http://mirrors.aliyun.com/pypi/packages/79/a8/83a52f422b1c041758fcfa3ac4438fc92a14e3cbe2b36f97282d973aff55/bidict-0.17.2.tar.gz (266kB)
100% |████████████████████████████████| 276kB 3.9MB/s
Stucked at installing bidict. Anyone offer a solution?
This way installing this package no longer will use easy_install to get such build dependencies when installing with pip 10+./
possibly with https://bitbucket.org/jwilk/python-afl à la https://github.com/tomviner/afl-fuzzing-demos#bidict (thanks @tomviner!)
https://files.pythonhosted.org/packages/b0/d8/f324b2a7a9fa098b800dcb4b34aa3f2df955caf9235f20d351ceed9e7c22/bidict-0.17.5-py3-none-any.whl shows that the wheel is only python 3 compatible, can we release the package as both python 2 and 3 compatible? https://wheel.readthedocs.io/en/stable/user_guide.html?highlight=universal#building-wheels
Some of the syntactic sugar in bidict causes a readability problem for me. Syntactic sugar is always going to be subjective, but I'd like to propose the removal of the overloading of slicing and bitwise negation - because .inv
is succinct and covers all these cases without needing the sugar:
~d
is clearer written as d.inv
d[:key]
is clearer written as d.inv[key]
.These don't need to be explained/learned in the same way as they follow from the same clear rule.
Naturally this would be a big breaking change but if bidict is not yet at a 1.0 release then this could presumably still be considered.
using ipython with python 3.7.1, I found that
In [95]: class Temp(object):
...: pass
...:
In [96]: a = Temp()
In [97]: hash(a)
Out[97]: -9223372036574570836
contradict with the descrpition
This is consistent with the fact that object implements hash(), but subclasses of object are not hashable by default.
in learn from bidict
Do i make this right because the behaviour of hash in new version of python differs
or just I misunderstand sth?
As promised by https://bidict.readthedocs.io/#python-2-eol.
Maybe after removing support for older versions of Python.
Ref:
Hi,
Pull request 107 has removed __all__
from bidict/__init__.py
.
This leads to implicit reexports of all the imported classes etc., which generates a error when typechecking with mypy in strict mode (which sets --no-implicit-reexport).
So for example with test.py...
from bidict import bidict, BidirectionalMapping
element_by_symbol: BidirectionalMapping[str, str] = bidict({'H': 'hydrogen'})
... due to disallowing implicit reexports, the imports will not be found by mypy, while the code obviously works:
$ mypy --strict .\test.py
test.py:1: error: Module 'bidict' has no attribute 'bidict'
test.py:1: error: Module 'bidict' has no attribute 'BidirectionalMapping'; maybe "MutableBidirectionalMapping"?
Found 2 errors in 1 file (checked 1 source file)
Was there some reasoning behind removing __all__
or could it be re-added?
Thanks in advance. :)
Since dict
's mutating methods aren't atomic (e.g. d[k] += 1, which is d[k] = d[k] + 1, which presents a race condition such that two threads running it at the same time may each see the same value for d[k], and it ends up set to d[k] + 1 rather than d[k] + 2), bidict
's mutating methods aren't atomic either. Worth documenting?
Performing a list comp with a bidict results in a 'not defined' error on Windows. Ive tried the same code on OSX 10.10 and it works fine.
In [1]: import bidict
In [2]: bd = bidict.bidict({1: 'a', 2: 'b', 3 : 'c'})
In [3]: bd[:'a']
Out[3]: 1
In [4]: names = [ 'a', 'b', 'c']
In [5]: names = ['a', 'b']
NameError Traceback (most recent call last)
----> 1 keys = [ bd[:x] for x in names ]
NameError: name 'bd' is not defined
I want to check whether your project is compatible with python 3.3. Your classifier only list 3.4 and 3.5.
I've installed py.test - no luck to run tests:
D:\work\OpenSource\bidict.git>py.test tests
usage: py.test [options] [file_or_dir] [file_or_dir] [...]
py.test: error: unrecognized arguments: --benchmark-save-data --benchmark-autosave --benchmark-group-by=name --benchmark-compare
inifile: D:\work\OpenSource\bidict.git\pytest.ini
rootdir: D:\work\OpenSource\bidict.git
I've tried python setup.py tests
- that commands downloads half of pypi, and then said:
----------------------------------------------------------------------
Ran 0 tests in 0.000s
OK
I've installed tox because that's what your contributing guide seems to suggest me. It said:
OSError: [WinError 193] %1 is not Win32 application
(that tried to run test.sh under the hood).
What I should try next?
This issue provides visibility into Renovate updates and their statuses. Learn more
These updates are awaiting their schedule. Click on a checkbox to get an update now.
These updates have all been created already. Click a checkbox below to force a retry/rebase of any.
Try replacing coverage.py with https://github.com/plasma-umass/slipcover and see if it speeds up running the tests with coverage enabled.
Using the source tarball from releases doesn't allow an installation.
$ tar -xzf bidict-0.21.2.tar.gz
$ cd bidict-0.21.2/
$ python3 -m venv .
$ source bin/activate
$ python3 setup.py develop
Traceback (most recent call last):
File "setup.py", line 94, in <module>
setup(
File "/home/bidict-0.21.2/lib64/python3.8/site-packages/setuptools/__init__.py", line 145, in setup
return distutils.core.setup(**attrs)
File "/usr/lib64/python3.8/distutils/core.py", line 108, in setup
_setup_distribution = dist = klass(attrs)
File "/home/bidict-0.21.2/lib64/python3.8/site-packages/setuptools/dist.py", line 446, in __init__
_Distribution.__init__(self, {
File "/usr/lib64/python3.8/distutils/dist.py", line 292, in __init__
self.finalize_options()
File "/home/bidict-0.21.2/lib64/python3.8/site-packages/setuptools/dist.py", line 735, in finalize_options
ep.load()(self, ep.name, value)
File "/home/bidict-0.21.2/.eggs/setuptools_scm-4.1.2-py3.8.egg/setuptools_scm/integration.py", line 17, in version_keyword
dist.metadata.version = _get_version(config)
File "/home/bidict-0.21.2/.eggs/setuptools_scm-4.1.2-py3.8.egg/setuptools_scm/__init__.py", line 148, in _get_version
parsed_version = _do_parse(config)
File "/home/bidict-0.21.2/.eggs/setuptools_scm-4.1.2-py3.8.egg/setuptools_scm/__init__.py", line 110, in _do_parse
raise LookupError(
LookupError: setuptools-scm was unable to detect version for '/home/bidict-0.21.2'.
Make sure you're either building from a fully intact git repository or PyPI tarballs. Most other sources (such as GitHub's tarballs, a git checkout without the .git folder) don't contain the necessary metadata and will not work.
For example, if you're using pip, instead of https://github.com/user/proj/archive/master.zip use git+https://github.com/user/proj.git#egg=proj
The tarball seems to be incomplete for the usage with setuptools-scm
.
...to verify that bidict performance is comparable to manually managing two dicts and catch any performance regressions.
Should read supported instead of suppored.
I have some data of coordinates stored in a bidict,debug info is like this:
(124.60132961215734, 43.75520239658435): (124.6013296121573, 43.7437499999993), (124.47646235458595, 43.762063234912446): (124.4770833333322, 43.756249999999305), (124.591724438498, 43.707862612120465): (124.58541666666568, 43.70208333333264),
Now I want to get key of (124.4770833333322, 43.756249999999305) which in values of the bidict,so I input the code:
source_coord = source_target_dict.get(coord) #coord = (124.4770833333322, 43.756249999999305)
And then debug info told me source coord is None
,what happened and how should I solve it?
issubclass(bidict, dict)
returns False
. We thus cannot pass it to function that test it. If dict
were at least at last place of mro
it would be settled.
The fact that every bidict creates an holds a reference to its inverse bidict, and each inverse holds a reference to the forward bidict, means that bidicts will create reference cycles.
This has two implications:
__del__()
methods won't be garbage collectable at all.I'm not sure how important this is, but it's more important the less you know about ways in which bidict is used.
A workaround might be not to hold a full reference to inv, but to instead hold a weak memoized reference. This would guarantee
d.inv.inv is d
but would allow immediate reclamation of either side of the bidict pair if no reference to them are held.
To quickly provide me with notice of your usage of bidict, please add a reaction to this issue. Hearing that people are using bidict is a powerful antidote to the loneliness of maintaining an open-source project by myself. 😅
Alternatively, you can create a dedicated issue if you'd like to tell me more about how you're using bidict and how it's treating you. I'd love to hear about your use case and if or how bidict could better support it.
Thanks for stopping by. 😊
❤️❤️❤️
If you are interested in reviewing changes to bidict, please 👍 (or better yet, comment, so I get an email) on this issue.
analogous to collections.defaultdict
using e.g. https://hypothesis.readthedocs.org
The undocumented bidict.invert()
appears to perform an "invert-in-place". This seems superfluous given .inv
; but naive use of this method could cause significant confusion about what state a bidict is in at what point in a program (consider beginners in particular). Without this there's no risk of holding a reference to a bidict that flip-flops in semantics.
A more expert programmer who wanted to do an in-place replacement of values, could use the same kind of approach as to mutate a normal dict in-place, eg:
vals = list(d.items())
d.clear()
d.inv.update(vals)
(Background: I work on a very large project (thousands of developers) where we see every type of mistake under the sun, and I can imagine this accidentally/foolishly being used to mutate global "constant" state causing hard-to-diagnose problems.)
import bidict
class Sub(bidict.loosebidict):
pass
b = Sub()
b['a'] = 1
....
RecursionError: maximum recursion depth exceeded while calling a Python object
This is because you are calling super(self.__class__, self)
instead of super()
Under python2.7 (at least) on Linux(Ubuntu14.10), pip uninstall from a virtualenv with bidict installed via pip install (using pip v1.5.6) says:
Can't uninstall 'bidict'. No files were found to uninstall.
Yet, at the python prompt:
>>> import bidict
>>> bidict.BidirectionalMapping({"a":1})
BidirectionalMapping({'a': 1})
>>>
viewitems() is no longer working
from bidict import bidict
d = bidict(a="b")
d.viewitems()
Now returns an error:
TypeError: init() takes exactly 2 arguments (1 given)
Looks like this is the cause 033083ca
Thanks,
I think exposing inverse
in addition to inv
would have two benefits:
I think it's important to remember that there is a big difference between reading .inv
when:
.inv
is really great in the first case, and is decently suggestive in the second case, and it's definitely easier to type, so I like it and think it's good to have it. But I think .inv
can be needlessly hard in the third and fourth case.
Because inverse
is not a "casual" word - it's easy to forget when we've internalized it and work with inverses of things regularly, but most people first explicitly learn it in technical contexts, like in math or formal logic or computer science.
For many practicing software developers the word itself doesn't come up that often, because when the concept does come up, it can be easier to find more common words to express it.
Relatedly, more and more software developers, both professionally and in open source communities, have English as their second language, or have picked up software as a practical tool without the more formal background.
I think when people are trying to understand some code, whether because they're new to it or haven't worked with it in a long time, having .inverse
reduces the amount of mental work they have to use just to idea-fit what the intent is, relative to .inv
, especially if they're not yet familiar with bidict
as a package.
TL;DR: I love .inv
for interactive use and quick work, but I'd like to have the option to write .inverse
when it helps people read and understand my code in the long term.
I recently tried using bidict
for the first time after not thinking about it for maybe four or six months, and I couldn't for the life of me remember off the top of my head how to get the inverse view.
Naturally, because Python is so helpfully discoverable, I did dir(my_bydict_instance)
and scanned the output (line-wrapped like it was on my 80-characters-wide terminal):
>>> dir(bd)
['_MutableMapping__marker', '_ON_DUP_OVERWRITE', '__abstractmethods__', '__class
__', '__contains__', '__copy__', '__delattr__', '__delitem__', '__dir__', '__doc
__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__get
state__', '__gt__', '__hash__', '__init__', '__inverted__', '__iter__', '__le__'
, '__len__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduc
e_ex__', '__repr__', '__setattr__', '__setitem__', '__setstate__', '__sizeof__',
'__slots__', '__str__', '__subclasshook__', '__weakref__', '_abc_cache', '_abc_
negative_cache', '_abc_negative_cache_version', '_abc_registry', '_dedup_item',
'_fwdm', '_fwdm_cls', '_get_on_dup', '_hash', '_init_inv', '_inv', '_inv_cls', '
_invm', '_invm_cls', '_invweak', '_isdupitem', '_isinv', '_pop', '_put', '_repr_
delegate', '_undo_write', '_update', '_update_with_rollback', '_write_item', 'cl
ear', 'copy', 'forceput', 'forceupdate', 'get', 'inv', 'items', 'keys', 'on_dup_
key', 'on_dup_kv', 'on_dup_val', 'pop', 'popitem', 'put', 'putall', 'setdefault'
, 'update', 'values']
For me, inv
just blended in with the other smaller default attributes, and more importantly, it didn't visually pattern-match for the kind of word I most readily thought of while trying to articulate in my head what I wanted.
Consider the appearance if we add an inverse
alias in there:
>>> dir(bd)
['_MutableMapping__marker', '_ON_DUP_OVERWRITE', '__abstractmethods__', '__class
__', '__contains__', '__copy__', '__delattr__', '__delitem__', '__dir__', '__doc
__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__get
state__', '__gt__', '__hash__', '__init__', '__inverted__', '__iter__', '__le__'
, '__len__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduc
e_ex__', '__repr__', '__setattr__', '__setitem__', '__setstate__', '__sizeof__',
'__slots__', '__str__', '__subclasshook__', '__weakref__', '_abc_cache', '_abc_
negative_cache', '_abc_negative_cache_version', '_abc_registry', '_dedup_item',
'_fwdm', '_fwdm_cls', '_get_on_dup', '_hash', '_init_inv', '_inv', '_inv_cls', '
_invm', '_invm_cls', '_invweak', '_isdupitem', '_isinv', '_pop', '_put', '_repr_
delegate', '_undo_write', '_update', '_update_with_rollback', '_write_item', 'cl
ear', 'copy', 'forceput', 'forceupdate', 'get', 'inv', 'inverse', 'items', 'keys
', 'on_dup_key', 'on_dup_kv', 'on_dup_val', 'pop', 'popitem', 'put', 'putall', '
setdefault', 'update', 'values']
The difference is slight and subtle, but I think it really helps, because if you don't know what word to look for, the word "inverse" jumps out more, and is more likely to visually pattern-match for a brain thinking of other related words like "reverse".
To be clear on that last bit, I fully agree that "inverse" is the more technically correct word than "reverse", and with the reasoning expressed in the Terminology addendum of the docs - that's not what I'm talking about. I'm just saying that we know some people think of "reverse" intuitively when thinking about a bijected mapping, and so having something that visually strongly pattern-matches it is a bonus to discoverability.
TL;DR: I think inverse
is more likely to more quickly jump out to a person unless they already know to look for inv
, especially if they have the word or similar words in mind already.
dir
as example to discoverability:Someone will probably want to reply that I could've just looked up the documentation for bidict
on the web instead, or that this would not be an issue on a modern IDE, or that doing help(my_bidict_instance)
would've made it easier, so I'm just going to preemptively address those now:
Web searches relative to dir
is like the human equivalent of a CPU getting data from disk instead of from L1 cache: it's must more out-of-band and requires orders of magnitude more mental, physical, and temporal overhead, as well as additional external conditions. It's easy to tune it out if you're already used to doing that, because human brains are good at that, but it's really noticeable when you're used to not having to do it.
IDEs and IPython and so on reduce the information-to-noise ratio vs. dir
, and can sometimes intelligently display type hints/inferences - still, as I'm sitting here looking at the auto-complete for my_bidict_instance.
in a couple of them, in moments when I manage to clear my mind of expectations, inv
doesn't really stand out prominently either. It's a lot easier to find, but the discoverability inefficiency isn't so much removed, as "dimmed". (Plus we don't always have access to such conveniences, depending on the systems or situations we're dealing with.)
help
provides a completely different kind of discoverability than dir
provides: help
gives you far more information to wade through, and all that extra information relative to dir
is about how the interfaces work, and is useless for the goal of remembering what a specific interface you already have in mind is called. It reduces information-to-noise ratio to use dir
instead of help
in such cases.
In short, my habit of calling dir
first developed because it gets me the right information faster most of the time, despite the unpleasantness and overhead of visually parsing the attribute names from the forest of single-quotes.
But even if dir
still doesn't feel like a good example, the overall discoverability point still applies, and even if the discoverability gain doesn't seem worth it, I think the intuition-and-reading-guiding obviousness of the full word is the main argument.
The old logo is black on a transparent background, and was only designed for use on pages with light backgrounds. The logo is not visible on pages with dark backgrounds, which has become a much more common way for it to be displayed now that GitHub supports dark mode.
<style>
elements. Can @media (prefers-color-scheme: dark)
be used in an SVG to make the same image file look good on both light and dark backgrounds? If so, if we switch the logo from PNGs to SVGs that use this trick, will it work everywhere the logo is displayed?{
braces around it }
(as @lordmauve once mocked up)? A full redesign is not out of scope here :)I see considerable value preventing people accidentally creating mappings that are not invertible. In our codebase, there are several hundred instances of code like
PRODUCT_REMAP = {... hundreds of lines ...}
REVERSE_PRODUCT_REMAP = dict((v, k) for k, v in PRODUCT_REMAP.iteritems())
A concern with these is that literals that were accidentally written to include duplicate values would create an incorrect inverse mapping.
Using bidict does little to improve matters. In code like that below, one of those keys will "win":
d = bidict({
'foo': 1,
... hundreds of lines ...
'bar': 1
})
This has the advantage that the inverse mapping will genuinely reflect the forward mapping, but it carries the disadvantage the mapping for one of the keys is lost. In many cases this is worse - for example, when the forward mapping is fundamental and the inverse mapping is just informational. The only reasonable solution in cases like these is to throw an exception for the programmer to deal with.
I suggest creating a "strictbidict" in which _put()
throws a CollapseException
if any value is duplicated, rather than dropping the previous key that maps to that value.
Hello,
I am creating a Python package that uses bidict. I'm wondering what type hinting I should assign to this data.
b: bidict[str, str] = bidict(
{
"H": "hydrogen",
"C": "carbon"
}
)
Is the bidict[str, str]
accurate? Thank you.
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.