question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Widgets are not unique when stored in a dict in sub-class

See original GitHub issue

This may be a python feature rather than an ipywidgets bug, but thought it was worth pointing out in case someone else has a similar issue and can’t figure it out.

I am subclassing HBox and VBox to create self-contained “combo-widgets”. However, I noticed that when I made independent instances of my combo-widgets, the widgets they contained seemed to be connected. It turns out that because I was storing the widgets in a dict the widgets were pointing to the same address.

Here is an MCVE:

import ipywidgets as widgets
class myBox(widgets.HBox):
    def __init__(self):
        self.widgets['innerbox']=widgets.Text()
        super().__init__(children=[self.widgets['innerbox']])
b1 = myBox()
print(id(b1.widgets['innerbox']))
b2 = myBox()
print(id(b1.widgets['innerbox']), id(b2.widgets['innerbox']))

Result is

140583624309712
140583623982352 140583623982352

It doesn’t happen if I store the inner widget like so

        self.innerbox=widgets.Text()

if I give the inner widgets different arguments every time they are instantiated they still end up pointing to the same place

import ipywidgets as widgets
import uuid
class myBox(widgets.HBox):
    def __init__(self):
        self.id = str(uuid.uuid1())
        self.widgets['innerbox']=widgets.Text(description=str(self.id))
        super().__init__(children=[self.widgets['innerbox']])
b1 = myBox()
print(b1.id, b1.widgets['innerbox'])
b2 = myBox()
print(b2.id, b2.widgets['innerbox'])
print(b1.id, b1.widgets['innerbox'])
print(id(b1.widgets['innerbox']), id(b2.widgets['innerbox']))
dfa1e66c-d865-11ea-bd85-fa163e8ac59c Text(value='', description='dfa1e66c-d865-11ea-bd85-fa163e8ac59c')
dfa587f4-d865-11ea-a034-fa163e8ac59c Text(value='', description='dfa587f4-d865-11ea-a034-fa163e8ac59c')
dfa1e66c-d865-11ea-bd85-fa163e8ac59c Text(value='', description='dfa587f4-d865-11ea-a034-fa163e8ac59c')
140583624267536 140583624267536

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:5 (4 by maintainers)

github_iconTop GitHub Comments

2reactions
ianhicommented, Aug 7, 2020

And I think the issue was coming up in this case because widgets is a class variable that is defined all the way back in the Widget base class

https://github.com/jupyter-widgets/ipywidgets/blob/6be18d9b75353f7b4a1c328c6ea06d8959f978f6/ipywidgets/widgets/widget.py#L266-L267

So the solution is either to redefine it for the instance as I did, or use a different variable name.

1reaction
ianhicommented, Aug 7, 2020

I think this is an issue of class instance variables vs class variables. I just read https://stackoverflow.com/questions/45284838/are-the-attributes-in-a-python-class-shared-or-not which I found to be helpful for understanding this.

I think this issue is in how you are (or are not) initializing self.widgets. If I change your example to this:

import ipywidgets as widgets
class myBox(widgets.HBox):
    def __init__(self):
        self.widgets = {}
        self.widgets['innerbox']=widgets.Text()
        super().__init__(children=[self.widgets['innerbox']])
b1 = myBox()
b2 = myBox()
print(id(b1.widgets['innerbox']) == id(b2.widgets['innerbox']))
print(b1.widgets is b2.widgets)

then I get the result I think you are expecting.

False
False
Read more comments on GitHub >

github_iconTop Results From Across the Web

Store Widgets in Dictionary - python - Stack Overflow
Can widget objects not be stored in dictionaries? Is there a way for me to ID widgets that would allow me to store...
Read more >
OrderedDict in Python - GeeksforGeeks
In Python 2.7 Ordered Dict is not dict subclass, it's a specialized container from collections module. Starting from Python 3.7, insertion order ...
Read more >
Widgets - Django documentation
A widget is Django's representation of an HTML input element. The widget handles the rendering of the HTML, and the extraction of data...
Read more >
15 things you should know about Dictionaries in Python
1. What is a Python dictionary? A dictionary is an unordered and mutable Python container that stores mappings of unique keys to values....
Read more >
tkinter.ttk — Tk themed widgets — Python 3.11.1 documentation
Each item is identified by a unique name. The widget will generate item IDs if they are not supplied by the caller. There...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found