Skip to content

How Box Handles Conversions

Chris Griffith edited this page Nov 2, 2024 · 2 revisions

When data is brought into a Box, the values are copied. In particular, when you import a dict or a list, changes to the original dict or list will not be reflected in the Box. In some future version of Box, the references to the values may be preserved, but at the moment, this is not possible.

For any other type, passing box_intact_types with a tuple listing the types to preserve will create a reference in the Box instead of a copy. In some future version of Box, subclasses of Box will automatically be considered a box_intact_type.

The examples below illustrate this:

Box does not create a connection to the original dictionary

from box import Box
from copy import deepcopy

original = {"key1": "value1", "key2": "value2", "key3": "value3"}
original_ref = original
original_copy = deepcopy(original)
box = Box(original)

print(f"""     original["key1"] ==> {original["key1"]}""")
# expect "value1"

# change the value in the original
original["key1"] = "new value"

print(f"""     original["key1"] ==> {original["key1"]}""")
# expect "newvalue"
print(f""" original_ref["key1"] ==> {original_ref["key1"]}""")
# expect "newvalue"
print(f"""original_copy["key1"] ==> {original_copy["key1"]}""")
# expect "value1"
print(f"""             box.key1 ==> {box.key1}""")
# expect "value1"

Produces the following output:

     original["key1"] ==> value1
     original["key1"] ==> new value
 original_ref["key1"] ==> new value
original_copy["key1"] ==> value1
             box.key1 ==> value1

Box does not create a connection to imported Boxes

from box import Box

box1 = Box({"key1": "value1", "key2": "value2", "key3": "value3"})
box2 = Box({"key4": "value4", "key5": "value5", "key6": "value6"})

box1.box2 = box2

box1.box2.key1 = "newvalue"

print(f"""         id(box2)  ==> {id(box2)}""")
print(f"""     id(box1.box2) ==> {id(box1.box2)}""")
print(f"""box1.box2 == box2  ==> {box1.box2 == box2}""")

print(f"""        mybox.key1 ==> {box1.key1} """)
print(f"""   box1.mybox.key1 ==> {box1.box2.key1} """)

Produces the following output:

         id(box2)  ==> 4404576032
     id(box1.box2) ==> 4406568000
box1.box2 == box2  ==> False
        mybox.key1 ==> value1
   box1.mybox.key1 ==> newvalue

Box does not create a connection to subclasses of Box

class MyBox(Box):
    pass

original= {"key1" : "value1", "key2": "value2", "key3": "value3"}

mybox = MyBox(original)

box = Box()

box.mybox = mybox

print(f"""         id(mybox)  ==> {id(mybox)}""")
print(f"""      id(box.mybox) ==> {id(box.mybox)}""")

mybox.key1 = "value4"

print(f"""         mybox.key1 ==> {mybox.key1}""")
print(f"""     box.mybox.key1 ==> {box.mybox.key1} """)
print(f"""box.mybox == mybox  ==> {box.mybox == mybox}""")

produces the following output:

         id(mybox)  ==> 4622158976
      id(box.mybox) ==> 4622157456
         mybox.key1 ==> value4
     box.mybox.key1 ==> value1
box.mybox == mybox  ==> False

Use box_intact_types to create a connection to subclasses of Box

class MyBox(Box):
    pass

original= {"key1" : "value1", "key2": "value2", "key3": "value3"}

mybox = MyBox(original)

box = Box(box_intact_types=(MyBox,))

box.mybox = mybox

print(f"""         id(mybox)  ==> {id(mybox)}""")
print(f"""      id(box.mybox) ==> {id(box.mybox)}""")

mybox.key1 = "value4"

print(f"""         mybox.key1 ==> {mybox.key1}""")
print(f"""     box.mybox.key1 ==> {box.mybox.key1} """)
print(f"""box.mybox == mybox  ==> {box.mybox == mybox}""")

Produces the following output:

         id(mybox)  ==> 4404364384
      id(box.mybox) ==> 4404364384
         mybox.key1 ==> value4
     box.mybox.key1 ==> value4
box.mybox == mybox  ==> True

This documentation provided Gustavo Arzola by via https://github.com/cdgriffith/Box/issues/280