memory-graph 0.3.53__tar.gz → 0.3.54__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. {memory_graph-0.3.53/memory_graph.egg-info → memory_graph-0.3.54}/PKG-INFO +33 -23
  2. {memory_graph-0.3.53 → memory_graph-0.3.54}/README.md +32 -22
  3. {memory_graph-0.3.53 → memory_graph-0.3.54}/images/binary.py +1 -1
  4. {memory_graph-0.3.53 → memory_graph-0.3.54}/memory_graph/__init__.py +1 -1
  5. {memory_graph-0.3.53 → memory_graph-0.3.54}/memory_graph/config.py +1 -0
  6. {memory_graph-0.3.53 → memory_graph-0.3.54}/memory_graph/config_default.py +6 -4
  7. {memory_graph-0.3.53 → memory_graph-0.3.54}/memory_graph/config_helpers.py +8 -1
  8. {memory_graph-0.3.53 → memory_graph-0.3.54/memory_graph.egg-info}/PKG-INFO +33 -23
  9. {memory_graph-0.3.53 → memory_graph-0.3.54}/pyproject.toml +1 -1
  10. {memory_graph-0.3.53 → memory_graph-0.3.54}/LICENSE.txt +0 -0
  11. {memory_graph-0.3.53 → memory_graph-0.3.54}/MANIFEST.in +0 -0
  12. {memory_graph-0.3.53 → memory_graph-0.3.54}/images/add_one.png +0 -0
  13. {memory_graph-0.3.53 → memory_graph-0.3.54}/images/add_one.py +0 -0
  14. {memory_graph-0.3.53 → memory_graph-0.3.54}/images/avltree.py +0 -0
  15. {memory_graph-0.3.53 → memory_graph-0.3.54}/images/avltree_dir.png +0 -0
  16. {memory_graph-0.3.53 → memory_graph-0.3.54}/images/avltree_fail.png +0 -0
  17. {memory_graph-0.3.53 → memory_graph-0.3.54}/images/avltree_key_value.png +0 -0
  18. {memory_graph-0.3.53 → memory_graph-0.3.54}/images/avltree_leaf.png +0 -0
  19. {memory_graph-0.3.53 → memory_graph-0.3.54}/images/avltree_linear.png +0 -0
  20. {memory_graph-0.3.53 → memory_graph-0.3.54}/images/avltree_table.png +0 -0
  21. {memory_graph-0.3.53 → memory_graph-0.3.54}/images/bin_search.png +0 -0
  22. {memory_graph-0.3.53 → memory_graph-0.3.54}/images/bin_search.py +0 -0
  23. {memory_graph-0.3.53 → memory_graph-0.3.54}/images/bin_search_linear.png +0 -0
  24. {memory_graph-0.3.53 → memory_graph-0.3.54}/images/bin_tree.gif +0 -0
  25. {memory_graph-0.3.53 → memory_graph-0.3.54}/images/bin_tree.png +0 -0
  26. {memory_graph-0.3.53 → memory_graph-0.3.54}/images/bin_tree.py +0 -0
  27. {memory_graph-0.3.53 → memory_graph-0.3.54}/images/binary.gif +0 -0
  28. {memory_graph-0.3.53 → memory_graph-0.3.54}/images/colab_example.png +0 -0
  29. {memory_graph-0.3.53 → memory_graph-0.3.54}/images/copy_immutable.png +0 -0
  30. {memory_graph-0.3.53 → memory_graph-0.3.54}/images/copy_immutable.py +0 -0
  31. {memory_graph-0.3.53 → memory_graph-0.3.54}/images/copy_method.png +0 -0
  32. {memory_graph-0.3.53 → memory_graph-0.3.54}/images/copy_method.py +0 -0
  33. {memory_graph-0.3.53 → memory_graph-0.3.54}/images/copy_mix.png +0 -0
  34. {memory_graph-0.3.53 → memory_graph-0.3.54}/images/copy_mix.py +0 -0
  35. {memory_graph-0.3.53 → memory_graph-0.3.54}/images/copy_mutable.png +0 -0
  36. {memory_graph-0.3.53 → memory_graph-0.3.54}/images/copy_mutable.py +0 -0
  37. {memory_graph-0.3.53 → memory_graph-0.3.54}/images/create_gif.sh +0 -0
  38. {memory_graph-0.3.53 → memory_graph-0.3.54}/images/create_images.sh +0 -0
  39. {memory_graph-0.3.53 → memory_graph-0.3.54}/images/debug_vscode.png +0 -0
  40. {memory_graph-0.3.53 → memory_graph-0.3.54}/images/debugging.gif +0 -0
  41. {memory_graph-0.3.53 → memory_graph-0.3.54}/images/debugging.py +0 -0
  42. {memory_graph-0.3.53 → memory_graph-0.3.54}/images/embedded1.png +0 -0
  43. {memory_graph-0.3.53 → memory_graph-0.3.54}/images/embedded2.png +0 -0
  44. {memory_graph-0.3.53 → memory_graph-0.3.54}/images/extension_numpy.png +0 -0
  45. {memory_graph-0.3.53 → memory_graph-0.3.54}/images/extension_numpy.py +0 -0
  46. {memory_graph-0.3.53 → memory_graph-0.3.54}/images/extension_pandas.png +0 -0
  47. {memory_graph-0.3.53 → memory_graph-0.3.54}/images/extension_pandas.py +0 -0
  48. {memory_graph-0.3.53 → memory_graph-0.3.54}/images/extension_torch.png +0 -0
  49. {memory_graph-0.3.53 → memory_graph-0.3.54}/images/extension_torch.py +0 -0
  50. {memory_graph-0.3.53 → memory_graph-0.3.54}/images/factorial.gif +0 -0
  51. {memory_graph-0.3.53 → memory_graph-0.3.54}/images/factorial.py +0 -0
  52. {memory_graph-0.3.53 → memory_graph-0.3.54}/images/hash_set.gif +0 -0
  53. {memory_graph-0.3.53 → memory_graph-0.3.54}/images/hash_set.png +0 -0
  54. {memory_graph-0.3.53 → memory_graph-0.3.54}/images/hash_set.py +0 -0
  55. {memory_graph-0.3.53 → memory_graph-0.3.54}/images/hidden_edges.png +0 -0
  56. {memory_graph-0.3.53 → memory_graph-0.3.54}/images/hidden_edges.py +0 -0
  57. {memory_graph-0.3.53 → memory_graph-0.3.54}/images/immutable.py +0 -0
  58. {memory_graph-0.3.53 → memory_graph-0.3.54}/images/immutable1.png +0 -0
  59. {memory_graph-0.3.53 → memory_graph-0.3.54}/images/immutable2.png +0 -0
  60. {memory_graph-0.3.53 → memory_graph-0.3.54}/images/introspect_depth.png +0 -0
  61. {memory_graph-0.3.53 → memory_graph-0.3.54}/images/introspect_depth.py +0 -0
  62. {memory_graph-0.3.53 → memory_graph-0.3.54}/images/ipython.png +0 -0
  63. {memory_graph-0.3.53 → memory_graph-0.3.54}/images/jupyter_example.png +0 -0
  64. {memory_graph-0.3.53 → memory_graph-0.3.54}/images/linked_list.gif +0 -0
  65. {memory_graph-0.3.53 → memory_graph-0.3.54}/images/linked_list.png +0 -0
  66. {memory_graph-0.3.53 → memory_graph-0.3.54}/images/linked_list.py +0 -0
  67. {memory_graph-0.3.53 → memory_graph-0.3.54}/images/many_types.png +0 -0
  68. {memory_graph-0.3.53 → memory_graph-0.3.54}/images/many_types.py +0 -0
  69. {memory_graph-0.3.53 → memory_graph-0.3.54}/images/marimo_example.png +0 -0
  70. {memory_graph-0.3.53 → memory_graph-0.3.54}/images/memory_graph_web_debugger.png +0 -0
  71. {memory_graph-0.3.53 → memory_graph-0.3.54}/images/mutable.py +0 -0
  72. {memory_graph-0.3.53 → memory_graph-0.3.54}/images/mutable1.png +0 -0
  73. {memory_graph-0.3.53 → memory_graph-0.3.54}/images/mutable2.png +0 -0
  74. {memory_graph-0.3.53 → memory_graph-0.3.54}/images/name_rebinding.py +0 -0
  75. {memory_graph-0.3.53 → memory_graph-0.3.54}/images/not_node_types.py +0 -0
  76. {memory_graph-0.3.53 → memory_graph-0.3.54}/images/power_set.gif +0 -0
  77. {memory_graph-0.3.53 → memory_graph-0.3.54}/images/power_set.py +0 -0
  78. {memory_graph-0.3.53 → memory_graph-0.3.54}/images/rebinding1.png +0 -0
  79. {memory_graph-0.3.53 → memory_graph-0.3.54}/images/rebinding2.png +0 -0
  80. {memory_graph-0.3.53 → memory_graph-0.3.54}/images/uva.png +0 -0
  81. {memory_graph-0.3.53 → memory_graph-0.3.54}/images/vscode_copying.gif +0 -0
  82. {memory_graph-0.3.53 → memory_graph-0.3.54}/memory_graph/call_stack.py +0 -0
  83. {memory_graph-0.3.53 → memory_graph-0.3.54}/memory_graph/extension_numpy.py +0 -0
  84. {memory_graph-0.3.53 → memory_graph-0.3.54}/memory_graph/extension_pandas.py +0 -0
  85. {memory_graph-0.3.53 → memory_graph-0.3.54}/memory_graph/extension_torch.py +0 -0
  86. {memory_graph-0.3.53 → memory_graph-0.3.54}/memory_graph/html_table.py +0 -0
  87. {memory_graph-0.3.53 → memory_graph-0.3.54}/memory_graph/list_view.py +0 -0
  88. {memory_graph-0.3.53 → memory_graph-0.3.54}/memory_graph/memory_to_nodes.py +0 -0
  89. {memory_graph-0.3.53 → memory_graph-0.3.54}/memory_graph/node_base.py +0 -0
  90. {memory_graph-0.3.53 → memory_graph-0.3.54}/memory_graph/node_key_value.py +0 -0
  91. {memory_graph-0.3.53 → memory_graph-0.3.54}/memory_graph/node_leaf.py +0 -0
  92. {memory_graph-0.3.53 → memory_graph-0.3.54}/memory_graph/node_linear.py +0 -0
  93. {memory_graph-0.3.53 → memory_graph-0.3.54}/memory_graph/node_table.py +0 -0
  94. {memory_graph-0.3.53 → memory_graph-0.3.54}/memory_graph/sequence.py +0 -0
  95. {memory_graph-0.3.53 → memory_graph-0.3.54}/memory_graph/slicer.py +0 -0
  96. {memory_graph-0.3.53 → memory_graph-0.3.54}/memory_graph/slices.py +0 -0
  97. {memory_graph-0.3.53 → memory_graph-0.3.54}/memory_graph/slices_iterator.py +0 -0
  98. {memory_graph-0.3.53 → memory_graph-0.3.54}/memory_graph/slices_table_iterator.py +0 -0
  99. {memory_graph-0.3.53 → memory_graph-0.3.54}/memory_graph/test.py +0 -0
  100. {memory_graph-0.3.53 → memory_graph-0.3.54}/memory_graph/test_max_graph_depth.py +0 -0
  101. {memory_graph-0.3.53 → memory_graph-0.3.54}/memory_graph/test_memory_graph.py +0 -0
  102. {memory_graph-0.3.53 → memory_graph-0.3.54}/memory_graph/test_memory_to_nodes.py +0 -0
  103. {memory_graph-0.3.53 → memory_graph-0.3.54}/memory_graph/test_sequence.py +0 -0
  104. {memory_graph-0.3.53 → memory_graph-0.3.54}/memory_graph/test_slicer.py +0 -0
  105. {memory_graph-0.3.53 → memory_graph-0.3.54}/memory_graph/test_slices.py +0 -0
  106. {memory_graph-0.3.53 → memory_graph-0.3.54}/memory_graph/test_slices_iterator.py +0 -0
  107. {memory_graph-0.3.53 → memory_graph-0.3.54}/memory_graph/utils.py +0 -0
  108. {memory_graph-0.3.53 → memory_graph-0.3.54}/memory_graph.egg-info/SOURCES.txt +0 -0
  109. {memory_graph-0.3.53 → memory_graph-0.3.54}/memory_graph.egg-info/dependency_links.txt +0 -0
  110. {memory_graph-0.3.53 → memory_graph-0.3.54}/memory_graph.egg-info/requires.txt +0 -0
  111. {memory_graph-0.3.53 → memory_graph-0.3.54}/memory_graph.egg-info/top_level.txt +0 -0
  112. {memory_graph-0.3.53 → memory_graph-0.3.54}/setup.cfg +0 -0
  113. {memory_graph-0.3.53 → memory_graph-0.3.54}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: memory_graph
3
- Version: 0.3.53
3
+ Version: 0.3.54
4
4
  Summary: Teaching tool and debugging aid in context of references, mutable data types, and shallow and deep copy.
5
5
  Author-email: Bas Terwijn <bterwijn@gmail.com>
6
6
  License: BSD 2-Clause License
@@ -52,7 +52,7 @@ Additionally [Graphviz](https://graphviz.org/download/) needs to be installed.
52
52
 
53
53
  # Highlights #
54
54
  ![vscode_copying.gif](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/vscode_copying.gif)
55
- Run a live demo in the 👉 [**Memory Graph Web Debugger**](https://memory-graph.com/#play) 👈 now, no installation required!
55
+ Run a live demo in the 👉 [**Memory Graph Web Debugger**](https://memory-graph.com/#breakpoints=8&continues=1&timestep=1.0&play) 👈 now, no installation required!
56
56
 
57
57
  - learn the right **mental model** to think about Python data (references, mutability, shallow vs deep copy)
58
58
  - **visualize the structure of your data** to easily understand and debug any data structure
@@ -164,8 +164,6 @@ A better way to understand what values are shared is to draw a graph using [memo
164
164
 
165
165
  [Troubleshooting](#troubleshooting)
166
166
 
167
- [Social Media](#social-media)
168
-
169
167
  [Other Packages](#other-packages)
170
168
 
171
169
  ## Author ##
@@ -174,6 +172,10 @@ Bas Terwijn
174
172
  ## Inspiration ##
175
173
  Inspired by [Python Tutor](https://pythontutor.com/).
176
174
 
175
+ ## Social Media #
176
+ * LinkedIn: https://www.linkedin.com/groups/13244150/
177
+ * Reddit: https://www.reddit.com/r/Python_memory_graph/
178
+
177
179
  ## Supported by ##
178
180
  <img src="https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/uva.png" alt="University of Amsterdam" width="600">
179
181
 
@@ -274,6 +276,8 @@ mg.show(locals())
274
276
  ```
275
277
  ![copy_method.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/copy_method.png)
276
278
 
279
+ Or see it in the [Memory Grah Web Debugger](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/custom_copy.py&breakpoints=15&continues=1&play).
280
+
277
281
  ## Name Rebinding ##
278
282
  When `a` and `b` share a mutable value, then changing the value of `b` changes the value of `a` and vice versa. However, reassigning `b` does not change `a`. When you reassign `b`, you only rebind the name `b` to another value without effecting any other variables.
279
283
 
@@ -348,6 +352,8 @@ print(f"a:{a} b:{b} c:{c}")
348
352
  ```
349
353
  ![add_one.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/add_one.png)
350
354
 
355
+ Or see it in the [Memory Grah Web Debugger](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/function_call.py&play).
356
+
351
357
  In the printed output only `a` is changed as a result of the function call:
352
358
  ```
353
359
  a:[4, 3, 2, 1] b:(4, 3, 2) c:[4, 3, 2]
@@ -355,6 +361,8 @@ a:[4, 3, 2, 1] b:(4, 3, 2) c:[4, 3, 2]
355
361
 
356
362
  This is because `b` is of immutable type 'tuple' so its value gets copied automatically when it is changed. And because the function is called with a copy of `c`, its original value is not changed by the function. The value of variable `a` is the only value of mutable type that is shared between the root stack frame **'0: \<module>'** and the **'1: add_one'** stack frame of the function so only that variable is affected as a result of the function call. The other changes remain confined to the local variables of the ```add_one()``` function.
357
363
 
364
+ Now is a good time to practice the Python Data Model. Here are [some exercises](https://github.com/bterwijn/memory_graph_videos/blob/main/exercises/exercises.md) on references, mutability, copies, and function calls.
365
+
358
366
  ## Block ##
359
367
  It is often helpful to temporarily block program execution to inspect the graph. For this we can use the `mg.block()` function:
360
368
 
@@ -384,16 +392,17 @@ def factorial(n):
384
392
 
385
393
  print( factorial(4) )
386
394
  ```
387
-
388
395
  ![factorial.gif](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/factorial.gif)
389
396
 
390
397
  and the result is: 1 x 2 x 3 x 4 = 24
391
398
 
392
- ## Binary ##
399
+ Or see it in the [Memory Grah Web Debugger](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/factorial.py&timestep=1.0&play).
400
+
401
+ ## Binary Convert ##
393
402
  A more interesting recursive example is function `binary()` that converts a decimal integer to binary representation.
394
403
  ```python
395
404
  import memory_graph as mg
396
- mg.config.type_to_vertical[list] = False # horizontal lists
405
+ mg.config.type_to_horizontal[list] = True # horizontal lists
397
406
 
398
407
  def binary(value: int) -> list[int]:
399
408
  mg.block(mg.show(), mg.stack())
@@ -411,6 +420,8 @@ print( binary(100) )
411
420
  1100100
412
421
  ```
413
422
 
423
+ Or see it in the [Memory Grah Web Debugger](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/binary_convert.py&timestep=1.0&play).
424
+
414
425
  ## Power Set ##
415
426
  A more complex recursive example is function `power_set()` where lists are shared by different function calls. A power set is the set of all subsets of a collection of values.
416
427
 
@@ -639,10 +650,10 @@ for i in range(n):
639
650
  Here we show values being inserted in a HashSet in PyCharm. When inserting the last value '44' we "Step Into" the code to show more of the details.
640
651
  ![images/hash_set.gif](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/hash_set.gif)
641
652
 
642
- Or see it in the [Memory Grah Web Debugger](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/hash_set.py&timestep=0.2&play).
653
+ Or see it in the [Memory Grah Web Debugger](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/hash_set.py&breakpoints=32&continues=1&timestep=0.5&play).
643
654
 
644
655
  # Configuration #
645
- Different aspects of memory_graph can be configured. The default configuration can be reset by calling 'mg.config_default.reset()'.
656
+ Different aspects of memory_graph can be configured. The default configuration can be reset by calling 'mg.config_default.reset()'. The Memory Graph Web Debugger gives examples of the [most important configurations](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/config.py&play).
646
657
 
647
658
  - ***mg.config.reopen_viewer*** : bool
648
659
  - If True the viewer is reopened each time show() is called, this might change window focus, default True.
@@ -677,8 +688,8 @@ Different aspects of memory_graph can be configured. The default configuration c
677
688
  - ***mg.config.type_to_color*** : dict[type, color]
678
689
  - Maps a type to the [graphviz color](https://graphviz.org/doc/info/colors.html) it gets in the graph.
679
690
 
680
- - ***mg.config.type_to_vertical*** : dict[type, bool]
681
- - Maps a type to its orientation. Use 'True' for vertical and 'False' for horizontal. If not specified Node_Linear and Node_Key_Value are vertical unless they have references to children.
691
+ - ***mg.config.type_to_horizontal*** : dict[type, bool]
692
+ - Maps a type to its orientation for Node_Linear and Node_Key_Value. Use 'True' for horizontal and 'False' for vertical. If not specified these nodes vertical unless they have references to children.
682
693
 
683
694
  - ***mg.config.type_to_slicer*** : dict[type, int]
684
695
  - Maps a type to a Slicer. A slicer determines how many elements of a data type are shown in the graph to prevent the graph from getting too big. 'Slicer()' does no slicing, 'Slicer(1,2,3)' shows just 1 element at the beginning, 2 in the middle, and 3 at the end.
@@ -735,7 +746,6 @@ mg.show(locals())
735
746
  ```
736
747
  ![extension_numpy.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/avltree_fail.png)
737
748
 
738
-
739
749
  ## All attributes using dir() ##
740
750
  A useful start is to give it some color, show the list of all its attributes using `dir()`, and setting an empty Slicer to see the attribute list in full.
741
751
 
@@ -757,7 +767,7 @@ mg.config.type_to_slicer[bintrees.avltree.Node] = mg.Slicer()
757
767
 
758
768
  mg.show(locals())
759
769
  ```
760
- ![extension_numpy.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/avltree_dir.png)
770
+ ![avltree_dir.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/avltree_dir.png)
761
771
 
762
772
  Next figure out what the attributes are you want to graph and choose a Node type, there are four options:
763
773
 
@@ -780,7 +790,7 @@ mg.config.type_to_node[bintrees.avltree.Node] = lambda data: mg.Node_Leaf(data,
780
790
 
781
791
  mg.show(locals())
782
792
  ```
783
- ![extension_numpy.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/avltree_leaf.png)
793
+ ![avltree_leaf.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/avltree_leaf.png)
784
794
 
785
795
  ## 2) Node_Linear ##
786
796
  Node_Linear shows multiple values in a line like a list.
@@ -804,7 +814,7 @@ mg.config.type_to_node[bintrees.avltree.Node] = lambda data: mg.Node_Linear(data
804
814
 
805
815
  mg.show(locals())
806
816
  ```
807
- ![extension_numpy.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/avltree_linear.png)
817
+ ![avltree_linear.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/avltree_linear.png)
808
818
 
809
819
  ## 3) Node_Key_Value ##
810
820
  Node_Key_Value shows key-value pairs like a dictionary. Note the required `items()` call at the end.
@@ -828,7 +838,7 @@ mg.config.type_to_node[bintrees.avltree.Node] = lambda data: mg.Node_Key_Value(d
828
838
 
829
839
  mg.show(locals())
830
840
  ```
831
- ![extension_numpy.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/avltree_key_value.png)
841
+ ![avltree_key_value.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/avltree_key_value.png)
832
842
 
833
843
  ## 4) Node_Table ##
834
844
  Node_Table shows all the values as a table.
@@ -850,7 +860,7 @@ mg.config.type_to_node[bintrees.avltree.Node] = lambda data: mg.Node_Table(data,
850
860
 
851
861
  mg.show(locals())
852
862
  ```
853
- ![extension_numpy.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/avltree_table.png)
863
+ ![avltree_table.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/avltree_table.png)
854
864
 
855
865
  ## Binary Search ##
856
866
  For binary search we can use a List_View class to represent a particular sublist without making a list copy.
@@ -955,7 +965,7 @@ mg.config.type_to_depth[B] = 3
955
965
  mg.config.type_to_depth[id(c)] = 2
956
966
  mg.show(locals())
957
967
  ```
958
- ![extension_numpy.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/introspect_depth.png)
968
+ ![introspect_depth.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/introspect_depth.png)
959
969
 
960
970
  ## Hidden Edges ##
961
971
 
@@ -971,7 +981,7 @@ for i in range(20):
971
981
 
972
982
  mg.show(locals())
973
983
  ```
974
- ![extension_numpy.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/hidden_edges.png)
984
+ ![hidden_edges.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/hidden_edges.png)
975
985
 
976
986
  # Extensions #
977
987
  Different extensions are available for types from other Python packages.
@@ -994,6 +1004,8 @@ mg.show(locals())
994
1004
  ```
995
1005
  ![extension_numpy.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/extension_numpy.png)
996
1006
 
1007
+ Or see it in the [Memory Grah Web Debugger](https://memory-graph.com/#micropip=numpy&codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/mg_numpy.py&continues=1).
1008
+
997
1009
  ## Pandas ##
998
1010
  Pandas types `Series` and `DataFrame` can be graphed with "memory_graph.extension_pandas":
999
1011
 
@@ -1013,6 +1025,8 @@ mg.show(locals())
1013
1025
  ```
1014
1026
  ![extension_pandas.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/extension_pandas.png)
1015
1027
 
1028
+ Or see it in the [Memory Grah Web Debugger](https://memory-graph.com/#micropip=pandas&codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/mg_pandas.py&continues=1).
1029
+
1016
1030
  ## PyTorch ##
1017
1031
  Torch type `tensor` can be graphed with "memory_graph.extension_torch":
1018
1032
 
@@ -1091,9 +1105,5 @@ $ bash create_gif.sh animated
1091
1105
 
1092
1106
  - When graph edges overlap it can be hard to distinguish them. Using an interactive graphviz viewer, such as [xdot](https://github.com/jrfonseca/xdot.py), on a '*.gv' DOT output file will help.
1093
1107
 
1094
- # Social Media #
1095
- * LinkedIn: https://www.linkedin.com/groups/13244150/
1096
- * Reddit: https://www.reddit.com/r/Python_memory_graph/
1097
-
1098
1108
  # Other Packages #
1099
1109
  The [memory_graph](https://pypi.org/project/memory-graph/) package visualizes your data. If instead you want to visualize function calls, check out the [invocation_tree](https://pypi.org/project/invocation-tree/) package.
@@ -7,7 +7,7 @@ Additionally [Graphviz](https://graphviz.org/download/) needs to be installed.
7
7
 
8
8
  # Highlights #
9
9
  ![vscode_copying.gif](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/vscode_copying.gif)
10
- Run a live demo in the 👉 [**Memory Graph Web Debugger**](https://memory-graph.com/#play) 👈 now, no installation required!
10
+ Run a live demo in the 👉 [**Memory Graph Web Debugger**](https://memory-graph.com/#breakpoints=8&continues=1&timestep=1.0&play) 👈 now, no installation required!
11
11
 
12
12
  - learn the right **mental model** to think about Python data (references, mutability, shallow vs deep copy)
13
13
  - **visualize the structure of your data** to easily understand and debug any data structure
@@ -119,8 +119,6 @@ A better way to understand what values are shared is to draw a graph using [memo
119
119
 
120
120
  [Troubleshooting](#troubleshooting)
121
121
 
122
- [Social Media](#social-media)
123
-
124
122
  [Other Packages](#other-packages)
125
123
 
126
124
  ## Author ##
@@ -129,6 +127,10 @@ Bas Terwijn
129
127
  ## Inspiration ##
130
128
  Inspired by [Python Tutor](https://pythontutor.com/).
131
129
 
130
+ ## Social Media #
131
+ * LinkedIn: https://www.linkedin.com/groups/13244150/
132
+ * Reddit: https://www.reddit.com/r/Python_memory_graph/
133
+
132
134
  ## Supported by ##
133
135
  <img src="https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/uva.png" alt="University of Amsterdam" width="600">
134
136
 
@@ -229,6 +231,8 @@ mg.show(locals())
229
231
  ```
230
232
  ![copy_method.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/copy_method.png)
231
233
 
234
+ Or see it in the [Memory Grah Web Debugger](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/custom_copy.py&breakpoints=15&continues=1&play).
235
+
232
236
  ## Name Rebinding ##
233
237
  When `a` and `b` share a mutable value, then changing the value of `b` changes the value of `a` and vice versa. However, reassigning `b` does not change `a`. When you reassign `b`, you only rebind the name `b` to another value without effecting any other variables.
234
238
 
@@ -303,6 +307,8 @@ print(f"a:{a} b:{b} c:{c}")
303
307
  ```
304
308
  ![add_one.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/add_one.png)
305
309
 
310
+ Or see it in the [Memory Grah Web Debugger](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/function_call.py&play).
311
+
306
312
  In the printed output only `a` is changed as a result of the function call:
307
313
  ```
308
314
  a:[4, 3, 2, 1] b:(4, 3, 2) c:[4, 3, 2]
@@ -310,6 +316,8 @@ a:[4, 3, 2, 1] b:(4, 3, 2) c:[4, 3, 2]
310
316
 
311
317
  This is because `b` is of immutable type 'tuple' so its value gets copied automatically when it is changed. And because the function is called with a copy of `c`, its original value is not changed by the function. The value of variable `a` is the only value of mutable type that is shared between the root stack frame **'0: \<module>'** and the **'1: add_one'** stack frame of the function so only that variable is affected as a result of the function call. The other changes remain confined to the local variables of the ```add_one()``` function.
312
318
 
319
+ Now is a good time to practice the Python Data Model. Here are [some exercises](https://github.com/bterwijn/memory_graph_videos/blob/main/exercises/exercises.md) on references, mutability, copies, and function calls.
320
+
313
321
  ## Block ##
314
322
  It is often helpful to temporarily block program execution to inspect the graph. For this we can use the `mg.block()` function:
315
323
 
@@ -339,16 +347,17 @@ def factorial(n):
339
347
 
340
348
  print( factorial(4) )
341
349
  ```
342
-
343
350
  ![factorial.gif](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/factorial.gif)
344
351
 
345
352
  and the result is: 1 x 2 x 3 x 4 = 24
346
353
 
347
- ## Binary ##
354
+ Or see it in the [Memory Grah Web Debugger](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/factorial.py&timestep=1.0&play).
355
+
356
+ ## Binary Convert ##
348
357
  A more interesting recursive example is function `binary()` that converts a decimal integer to binary representation.
349
358
  ```python
350
359
  import memory_graph as mg
351
- mg.config.type_to_vertical[list] = False # horizontal lists
360
+ mg.config.type_to_horizontal[list] = True # horizontal lists
352
361
 
353
362
  def binary(value: int) -> list[int]:
354
363
  mg.block(mg.show(), mg.stack())
@@ -366,6 +375,8 @@ print( binary(100) )
366
375
  1100100
367
376
  ```
368
377
 
378
+ Or see it in the [Memory Grah Web Debugger](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/binary_convert.py&timestep=1.0&play).
379
+
369
380
  ## Power Set ##
370
381
  A more complex recursive example is function `power_set()` where lists are shared by different function calls. A power set is the set of all subsets of a collection of values.
371
382
 
@@ -594,10 +605,10 @@ for i in range(n):
594
605
  Here we show values being inserted in a HashSet in PyCharm. When inserting the last value '44' we "Step Into" the code to show more of the details.
595
606
  ![images/hash_set.gif](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/hash_set.gif)
596
607
 
597
- Or see it in the [Memory Grah Web Debugger](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/hash_set.py&timestep=0.2&play).
608
+ Or see it in the [Memory Grah Web Debugger](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/hash_set.py&breakpoints=32&continues=1&timestep=0.5&play).
598
609
 
599
610
  # Configuration #
600
- Different aspects of memory_graph can be configured. The default configuration can be reset by calling 'mg.config_default.reset()'.
611
+ Different aspects of memory_graph can be configured. The default configuration can be reset by calling 'mg.config_default.reset()'. The Memory Graph Web Debugger gives examples of the [most important configurations](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/config.py&play).
601
612
 
602
613
  - ***mg.config.reopen_viewer*** : bool
603
614
  - If True the viewer is reopened each time show() is called, this might change window focus, default True.
@@ -632,8 +643,8 @@ Different aspects of memory_graph can be configured. The default configuration c
632
643
  - ***mg.config.type_to_color*** : dict[type, color]
633
644
  - Maps a type to the [graphviz color](https://graphviz.org/doc/info/colors.html) it gets in the graph.
634
645
 
635
- - ***mg.config.type_to_vertical*** : dict[type, bool]
636
- - Maps a type to its orientation. Use 'True' for vertical and 'False' for horizontal. If not specified Node_Linear and Node_Key_Value are vertical unless they have references to children.
646
+ - ***mg.config.type_to_horizontal*** : dict[type, bool]
647
+ - Maps a type to its orientation for Node_Linear and Node_Key_Value. Use 'True' for horizontal and 'False' for vertical. If not specified these nodes vertical unless they have references to children.
637
648
 
638
649
  - ***mg.config.type_to_slicer*** : dict[type, int]
639
650
  - Maps a type to a Slicer. A slicer determines how many elements of a data type are shown in the graph to prevent the graph from getting too big. 'Slicer()' does no slicing, 'Slicer(1,2,3)' shows just 1 element at the beginning, 2 in the middle, and 3 at the end.
@@ -690,7 +701,6 @@ mg.show(locals())
690
701
  ```
691
702
  ![extension_numpy.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/avltree_fail.png)
692
703
 
693
-
694
704
  ## All attributes using dir() ##
695
705
  A useful start is to give it some color, show the list of all its attributes using `dir()`, and setting an empty Slicer to see the attribute list in full.
696
706
 
@@ -712,7 +722,7 @@ mg.config.type_to_slicer[bintrees.avltree.Node] = mg.Slicer()
712
722
 
713
723
  mg.show(locals())
714
724
  ```
715
- ![extension_numpy.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/avltree_dir.png)
725
+ ![avltree_dir.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/avltree_dir.png)
716
726
 
717
727
  Next figure out what the attributes are you want to graph and choose a Node type, there are four options:
718
728
 
@@ -735,7 +745,7 @@ mg.config.type_to_node[bintrees.avltree.Node] = lambda data: mg.Node_Leaf(data,
735
745
 
736
746
  mg.show(locals())
737
747
  ```
738
- ![extension_numpy.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/avltree_leaf.png)
748
+ ![avltree_leaf.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/avltree_leaf.png)
739
749
 
740
750
  ## 2) Node_Linear ##
741
751
  Node_Linear shows multiple values in a line like a list.
@@ -759,7 +769,7 @@ mg.config.type_to_node[bintrees.avltree.Node] = lambda data: mg.Node_Linear(data
759
769
 
760
770
  mg.show(locals())
761
771
  ```
762
- ![extension_numpy.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/avltree_linear.png)
772
+ ![avltree_linear.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/avltree_linear.png)
763
773
 
764
774
  ## 3) Node_Key_Value ##
765
775
  Node_Key_Value shows key-value pairs like a dictionary. Note the required `items()` call at the end.
@@ -783,7 +793,7 @@ mg.config.type_to_node[bintrees.avltree.Node] = lambda data: mg.Node_Key_Value(d
783
793
 
784
794
  mg.show(locals())
785
795
  ```
786
- ![extension_numpy.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/avltree_key_value.png)
796
+ ![avltree_key_value.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/avltree_key_value.png)
787
797
 
788
798
  ## 4) Node_Table ##
789
799
  Node_Table shows all the values as a table.
@@ -805,7 +815,7 @@ mg.config.type_to_node[bintrees.avltree.Node] = lambda data: mg.Node_Table(data,
805
815
 
806
816
  mg.show(locals())
807
817
  ```
808
- ![extension_numpy.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/avltree_table.png)
818
+ ![avltree_table.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/avltree_table.png)
809
819
 
810
820
  ## Binary Search ##
811
821
  For binary search we can use a List_View class to represent a particular sublist without making a list copy.
@@ -910,7 +920,7 @@ mg.config.type_to_depth[B] = 3
910
920
  mg.config.type_to_depth[id(c)] = 2
911
921
  mg.show(locals())
912
922
  ```
913
- ![extension_numpy.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/introspect_depth.png)
923
+ ![introspect_depth.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/introspect_depth.png)
914
924
 
915
925
  ## Hidden Edges ##
916
926
 
@@ -926,7 +936,7 @@ for i in range(20):
926
936
 
927
937
  mg.show(locals())
928
938
  ```
929
- ![extension_numpy.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/hidden_edges.png)
939
+ ![hidden_edges.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/hidden_edges.png)
930
940
 
931
941
  # Extensions #
932
942
  Different extensions are available for types from other Python packages.
@@ -949,6 +959,8 @@ mg.show(locals())
949
959
  ```
950
960
  ![extension_numpy.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/extension_numpy.png)
951
961
 
962
+ Or see it in the [Memory Grah Web Debugger](https://memory-graph.com/#micropip=numpy&codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/mg_numpy.py&continues=1).
963
+
952
964
  ## Pandas ##
953
965
  Pandas types `Series` and `DataFrame` can be graphed with "memory_graph.extension_pandas":
954
966
 
@@ -968,6 +980,8 @@ mg.show(locals())
968
980
  ```
969
981
  ![extension_pandas.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/extension_pandas.png)
970
982
 
983
+ Or see it in the [Memory Grah Web Debugger](https://memory-graph.com/#micropip=pandas&codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/mg_pandas.py&continues=1).
984
+
971
985
  ## PyTorch ##
972
986
  Torch type `tensor` can be graphed with "memory_graph.extension_torch":
973
987
 
@@ -1046,9 +1060,5 @@ $ bash create_gif.sh animated
1046
1060
 
1047
1061
  - When graph edges overlap it can be hard to distinguish them. Using an interactive graphviz viewer, such as [xdot](https://github.com/jrfonseca/xdot.py), on a '*.gv' DOT output file will help.
1048
1062
 
1049
- # Social Media #
1050
- * LinkedIn: https://www.linkedin.com/groups/13244150/
1051
- * Reddit: https://www.reddit.com/r/Python_memory_graph/
1052
-
1053
1063
  # Other Packages #
1054
1064
  The [memory_graph](https://pypi.org/project/memory-graph/) package visualizes your data. If instead you want to visualize function calls, check out the [invocation_tree](https://pypi.org/project/invocation-tree/) package.
@@ -1,6 +1,6 @@
1
1
  import memory_graph as mg
2
2
  import typing
3
- mg.config.type_to_vertical[list] = False # horizontal lists
3
+ mg.config.type_to_horizontal[list] = True # horizontal lists
4
4
 
5
5
  def binary(value: int) -> typing.List[int]:
6
6
  mg.render(mg.stack(), 'binary.png', numbered=True)
@@ -2,7 +2,7 @@
2
2
  # Copyright (c) 2023, Bas Terwijn.
3
3
  # SPDX-License-Identifier: BSD-2-Clause
4
4
 
5
- __version__ = "0.3.53"
5
+ __version__ = "0.3.54"
6
6
  __author__ = 'Bas Terwijn'
7
7
 
8
8
  import memory_graph.memory_to_nodes as memory_to_nodes
@@ -36,6 +36,7 @@ type_to_node = { }
36
36
 
37
37
  type_to_color = { }
38
38
 
39
+ type_to_horizontal = { }
39
40
  type_to_vertical = { }
40
41
 
41
42
  type_to_slicer = { }
@@ -103,10 +103,12 @@ def reset():
103
103
  }
104
104
 
105
105
 
106
- """ Types that will be visualized in vertical orientation if 'True', or horizontal orientation
107
- if 'False'. Otherwise the Node decides based on it having references."""
108
- config.type_to_vertical_orientation = {
109
- }
106
+ """ Types that will be visualized in horizontal or vertical orientation based on a True/False value.
107
+ The 'type_to_horizontal' takes precedence over 'type_to_vertical'.
108
+ If no boolean value is present the Node decides based on it having references."""
109
+ config.type_to_horizontal = {}
110
+ config.type_to_vertical = {}
111
+
110
112
 
111
113
  """ Slicer objects for different types. """
112
114
  config.type_to_slicer = {
@@ -23,10 +23,17 @@ def get_color(node, default='white'):
23
23
  default)
24
24
 
25
25
  def get_vertical(node, default):
26
+ horizontal = get_property(node.get_id(),
27
+ node.get_type(),
28
+ type(node),
29
+ config.type_to_horizontal,
30
+ None)
31
+ if isinstance(horizontal, bool):
32
+ return not horizontal
26
33
  return get_property(node.get_id(),
27
34
  node.get_type(),
28
35
  type(node),
29
- config.type_to_vertical,
36
+ config.type_to_vertical,
30
37
  default)
31
38
 
32
39
  def get_slicer(node, data, default=Slicer(3,2,3)):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: memory_graph
3
- Version: 0.3.53
3
+ Version: 0.3.54
4
4
  Summary: Teaching tool and debugging aid in context of references, mutable data types, and shallow and deep copy.
5
5
  Author-email: Bas Terwijn <bterwijn@gmail.com>
6
6
  License: BSD 2-Clause License
@@ -52,7 +52,7 @@ Additionally [Graphviz](https://graphviz.org/download/) needs to be installed.
52
52
 
53
53
  # Highlights #
54
54
  ![vscode_copying.gif](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/vscode_copying.gif)
55
- Run a live demo in the 👉 [**Memory Graph Web Debugger**](https://memory-graph.com/#play) 👈 now, no installation required!
55
+ Run a live demo in the 👉 [**Memory Graph Web Debugger**](https://memory-graph.com/#breakpoints=8&continues=1&timestep=1.0&play) 👈 now, no installation required!
56
56
 
57
57
  - learn the right **mental model** to think about Python data (references, mutability, shallow vs deep copy)
58
58
  - **visualize the structure of your data** to easily understand and debug any data structure
@@ -164,8 +164,6 @@ A better way to understand what values are shared is to draw a graph using [memo
164
164
 
165
165
  [Troubleshooting](#troubleshooting)
166
166
 
167
- [Social Media](#social-media)
168
-
169
167
  [Other Packages](#other-packages)
170
168
 
171
169
  ## Author ##
@@ -174,6 +172,10 @@ Bas Terwijn
174
172
  ## Inspiration ##
175
173
  Inspired by [Python Tutor](https://pythontutor.com/).
176
174
 
175
+ ## Social Media #
176
+ * LinkedIn: https://www.linkedin.com/groups/13244150/
177
+ * Reddit: https://www.reddit.com/r/Python_memory_graph/
178
+
177
179
  ## Supported by ##
178
180
  <img src="https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/uva.png" alt="University of Amsterdam" width="600">
179
181
 
@@ -274,6 +276,8 @@ mg.show(locals())
274
276
  ```
275
277
  ![copy_method.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/copy_method.png)
276
278
 
279
+ Or see it in the [Memory Grah Web Debugger](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/custom_copy.py&breakpoints=15&continues=1&play).
280
+
277
281
  ## Name Rebinding ##
278
282
  When `a` and `b` share a mutable value, then changing the value of `b` changes the value of `a` and vice versa. However, reassigning `b` does not change `a`. When you reassign `b`, you only rebind the name `b` to another value without effecting any other variables.
279
283
 
@@ -348,6 +352,8 @@ print(f"a:{a} b:{b} c:{c}")
348
352
  ```
349
353
  ![add_one.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/add_one.png)
350
354
 
355
+ Or see it in the [Memory Grah Web Debugger](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/function_call.py&play).
356
+
351
357
  In the printed output only `a` is changed as a result of the function call:
352
358
  ```
353
359
  a:[4, 3, 2, 1] b:(4, 3, 2) c:[4, 3, 2]
@@ -355,6 +361,8 @@ a:[4, 3, 2, 1] b:(4, 3, 2) c:[4, 3, 2]
355
361
 
356
362
  This is because `b` is of immutable type 'tuple' so its value gets copied automatically when it is changed. And because the function is called with a copy of `c`, its original value is not changed by the function. The value of variable `a` is the only value of mutable type that is shared between the root stack frame **'0: \<module>'** and the **'1: add_one'** stack frame of the function so only that variable is affected as a result of the function call. The other changes remain confined to the local variables of the ```add_one()``` function.
357
363
 
364
+ Now is a good time to practice the Python Data Model. Here are [some exercises](https://github.com/bterwijn/memory_graph_videos/blob/main/exercises/exercises.md) on references, mutability, copies, and function calls.
365
+
358
366
  ## Block ##
359
367
  It is often helpful to temporarily block program execution to inspect the graph. For this we can use the `mg.block()` function:
360
368
 
@@ -384,16 +392,17 @@ def factorial(n):
384
392
 
385
393
  print( factorial(4) )
386
394
  ```
387
-
388
395
  ![factorial.gif](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/factorial.gif)
389
396
 
390
397
  and the result is: 1 x 2 x 3 x 4 = 24
391
398
 
392
- ## Binary ##
399
+ Or see it in the [Memory Grah Web Debugger](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/factorial.py&timestep=1.0&play).
400
+
401
+ ## Binary Convert ##
393
402
  A more interesting recursive example is function `binary()` that converts a decimal integer to binary representation.
394
403
  ```python
395
404
  import memory_graph as mg
396
- mg.config.type_to_vertical[list] = False # horizontal lists
405
+ mg.config.type_to_horizontal[list] = True # horizontal lists
397
406
 
398
407
  def binary(value: int) -> list[int]:
399
408
  mg.block(mg.show(), mg.stack())
@@ -411,6 +420,8 @@ print( binary(100) )
411
420
  1100100
412
421
  ```
413
422
 
423
+ Or see it in the [Memory Grah Web Debugger](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/binary_convert.py&timestep=1.0&play).
424
+
414
425
  ## Power Set ##
415
426
  A more complex recursive example is function `power_set()` where lists are shared by different function calls. A power set is the set of all subsets of a collection of values.
416
427
 
@@ -639,10 +650,10 @@ for i in range(n):
639
650
  Here we show values being inserted in a HashSet in PyCharm. When inserting the last value '44' we "Step Into" the code to show more of the details.
640
651
  ![images/hash_set.gif](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/hash_set.gif)
641
652
 
642
- Or see it in the [Memory Grah Web Debugger](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/hash_set.py&timestep=0.2&play).
653
+ Or see it in the [Memory Grah Web Debugger](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/hash_set.py&breakpoints=32&continues=1&timestep=0.5&play).
643
654
 
644
655
  # Configuration #
645
- Different aspects of memory_graph can be configured. The default configuration can be reset by calling 'mg.config_default.reset()'.
656
+ Different aspects of memory_graph can be configured. The default configuration can be reset by calling 'mg.config_default.reset()'. The Memory Graph Web Debugger gives examples of the [most important configurations](https://memory-graph.com/#codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/config.py&play).
646
657
 
647
658
  - ***mg.config.reopen_viewer*** : bool
648
659
  - If True the viewer is reopened each time show() is called, this might change window focus, default True.
@@ -677,8 +688,8 @@ Different aspects of memory_graph can be configured. The default configuration c
677
688
  - ***mg.config.type_to_color*** : dict[type, color]
678
689
  - Maps a type to the [graphviz color](https://graphviz.org/doc/info/colors.html) it gets in the graph.
679
690
 
680
- - ***mg.config.type_to_vertical*** : dict[type, bool]
681
- - Maps a type to its orientation. Use 'True' for vertical and 'False' for horizontal. If not specified Node_Linear and Node_Key_Value are vertical unless they have references to children.
691
+ - ***mg.config.type_to_horizontal*** : dict[type, bool]
692
+ - Maps a type to its orientation for Node_Linear and Node_Key_Value. Use 'True' for horizontal and 'False' for vertical. If not specified these nodes vertical unless they have references to children.
682
693
 
683
694
  - ***mg.config.type_to_slicer*** : dict[type, int]
684
695
  - Maps a type to a Slicer. A slicer determines how many elements of a data type are shown in the graph to prevent the graph from getting too big. 'Slicer()' does no slicing, 'Slicer(1,2,3)' shows just 1 element at the beginning, 2 in the middle, and 3 at the end.
@@ -735,7 +746,6 @@ mg.show(locals())
735
746
  ```
736
747
  ![extension_numpy.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/avltree_fail.png)
737
748
 
738
-
739
749
  ## All attributes using dir() ##
740
750
  A useful start is to give it some color, show the list of all its attributes using `dir()`, and setting an empty Slicer to see the attribute list in full.
741
751
 
@@ -757,7 +767,7 @@ mg.config.type_to_slicer[bintrees.avltree.Node] = mg.Slicer()
757
767
 
758
768
  mg.show(locals())
759
769
  ```
760
- ![extension_numpy.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/avltree_dir.png)
770
+ ![avltree_dir.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/avltree_dir.png)
761
771
 
762
772
  Next figure out what the attributes are you want to graph and choose a Node type, there are four options:
763
773
 
@@ -780,7 +790,7 @@ mg.config.type_to_node[bintrees.avltree.Node] = lambda data: mg.Node_Leaf(data,
780
790
 
781
791
  mg.show(locals())
782
792
  ```
783
- ![extension_numpy.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/avltree_leaf.png)
793
+ ![avltree_leaf.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/avltree_leaf.png)
784
794
 
785
795
  ## 2) Node_Linear ##
786
796
  Node_Linear shows multiple values in a line like a list.
@@ -804,7 +814,7 @@ mg.config.type_to_node[bintrees.avltree.Node] = lambda data: mg.Node_Linear(data
804
814
 
805
815
  mg.show(locals())
806
816
  ```
807
- ![extension_numpy.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/avltree_linear.png)
817
+ ![avltree_linear.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/avltree_linear.png)
808
818
 
809
819
  ## 3) Node_Key_Value ##
810
820
  Node_Key_Value shows key-value pairs like a dictionary. Note the required `items()` call at the end.
@@ -828,7 +838,7 @@ mg.config.type_to_node[bintrees.avltree.Node] = lambda data: mg.Node_Key_Value(d
828
838
 
829
839
  mg.show(locals())
830
840
  ```
831
- ![extension_numpy.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/avltree_key_value.png)
841
+ ![avltree_key_value.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/avltree_key_value.png)
832
842
 
833
843
  ## 4) Node_Table ##
834
844
  Node_Table shows all the values as a table.
@@ -850,7 +860,7 @@ mg.config.type_to_node[bintrees.avltree.Node] = lambda data: mg.Node_Table(data,
850
860
 
851
861
  mg.show(locals())
852
862
  ```
853
- ![extension_numpy.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/avltree_table.png)
863
+ ![avltree_table.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/avltree_table.png)
854
864
 
855
865
  ## Binary Search ##
856
866
  For binary search we can use a List_View class to represent a particular sublist without making a list copy.
@@ -955,7 +965,7 @@ mg.config.type_to_depth[B] = 3
955
965
  mg.config.type_to_depth[id(c)] = 2
956
966
  mg.show(locals())
957
967
  ```
958
- ![extension_numpy.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/introspect_depth.png)
968
+ ![introspect_depth.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/introspect_depth.png)
959
969
 
960
970
  ## Hidden Edges ##
961
971
 
@@ -971,7 +981,7 @@ for i in range(20):
971
981
 
972
982
  mg.show(locals())
973
983
  ```
974
- ![extension_numpy.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/hidden_edges.png)
984
+ ![hidden_edges.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/hidden_edges.png)
975
985
 
976
986
  # Extensions #
977
987
  Different extensions are available for types from other Python packages.
@@ -994,6 +1004,8 @@ mg.show(locals())
994
1004
  ```
995
1005
  ![extension_numpy.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/extension_numpy.png)
996
1006
 
1007
+ Or see it in the [Memory Grah Web Debugger](https://memory-graph.com/#micropip=numpy&codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/mg_numpy.py&continues=1).
1008
+
997
1009
  ## Pandas ##
998
1010
  Pandas types `Series` and `DataFrame` can be graphed with "memory_graph.extension_pandas":
999
1011
 
@@ -1013,6 +1025,8 @@ mg.show(locals())
1013
1025
  ```
1014
1026
  ![extension_pandas.png](https://raw.githubusercontent.com/bterwijn/memory_graph/main/images/extension_pandas.png)
1015
1027
 
1028
+ Or see it in the [Memory Grah Web Debugger](https://memory-graph.com/#micropip=pandas&codeurl=https://raw.githubusercontent.com/bterwijn/memory_graph/refs/heads/main/src/mg_pandas.py&continues=1).
1029
+
1016
1030
  ## PyTorch ##
1017
1031
  Torch type `tensor` can be graphed with "memory_graph.extension_torch":
1018
1032
 
@@ -1091,9 +1105,5 @@ $ bash create_gif.sh animated
1091
1105
 
1092
1106
  - When graph edges overlap it can be hard to distinguish them. Using an interactive graphviz viewer, such as [xdot](https://github.com/jrfonseca/xdot.py), on a '*.gv' DOT output file will help.
1093
1107
 
1094
- # Social Media #
1095
- * LinkedIn: https://www.linkedin.com/groups/13244150/
1096
- * Reddit: https://www.reddit.com/r/Python_memory_graph/
1097
-
1098
1108
  # Other Packages #
1099
1109
  The [memory_graph](https://pypi.org/project/memory-graph/) package visualizes your data. If instead you want to visualize function calls, check out the [invocation_tree](https://pypi.org/project/invocation-tree/) package.
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "memory_graph"
7
- version = "0.3.53"
7
+ version = "0.3.54"
8
8
  description = "Teaching tool and debugging aid in context of references, mutable data types, and shallow and deep copy."
9
9
  authors = [
10
10
  {name = "Bas Terwijn", email = "bterwijn@gmail.com"}
File without changes
File without changes
File without changes
File without changes