Visitor
Visitor is a tiny Python library designed to facilitate the implementation of the visitor design pattern. It provides a base `Visitor` class to help separate algorithms from the object structures they operate on, addressing the peculiarities of dynamic typing in Python for this pattern. The library is very small, and its documentation suggests that users might consider copying the source code directly into their projects. The current version is 0.1.3, with the last release dating back to 2016, indicating a very mature or inactive maintenance cadence.
Warnings
- gotcha The library has not been updated since May 2016, with version 0.1.3 being the latest. While the core visitor pattern implementation is stable, it means the library is not actively maintained and may not leverage newer Python features or address modern compatibility concerns.
- gotcha The documentation itself suggests that the library is so small you might be better off copying and pasting the source directly into your project. This further emphasizes its lack of active development and its minimal footprint.
- gotcha Naming a local file or module `visitor.py` can lead to a naming conflict, shadowing this installed library or the more common design pattern concept itself. This is a general Python footgun when using simple, descriptive names for modules.
Install
-
pip install visitor
Imports
- Visitor
from visitor import Visitor
Quickstart
from visitor import Visitor
class JSONEncoder(Visitor):
def __init__(self):
self.output = []
def visit_list(self, obj):
self.output.append('[')
for item in obj:
self.visit(item)
self.output.append(',')
if len(obj) > 0: # Remove trailing comma if list is not empty
self.output.pop()
self.output.append(']')
def visit_dict(self, obj):
self.output.append('{')
for key, value in obj.items():
self.visit(key)
self.output.append(':')
self.visit(value)
self.output.append(',')
if len(obj) > 0: # Remove trailing comma if dict is not empty
self.output.pop()
self.output.append('}')
def visit_str(self, obj):
self.output.append(f'"{obj}"')
def visit_int(self, obj):
self.output.append(str(obj))
def visit_float(self, obj):
self.output.append(str(obj))
def generic_visit(self, obj):
# Fallback for types not explicitly handled, e.g., None, bool
self.output.append(str(obj).lower() if isinstance(obj, bool) else 'null' if obj is None else repr(obj))
def encode(self, obj):
self.output = []
self.visit(obj)
return ''.join(self.output)
# Example Usage:
data = {
'name': 'Alice',
'age': 30,
'isStudent': False,
'courses': ['Math', 'Science'],
'address': {'city': 'New York', 'zip': 10001},
'grades': [95, 88.5, 76],
'null_field': None
}
encoder = JSONEncoder()
json_string = encoder.encode(data)
print(json_string)
expected_output = '{"name":"Alice","age":30,"isStudent":false,"courses":["Math","Science"],"address":{"city":"New York","zip":10001},"grades":[95,88.5,76],"null_field":null}'
assert json_string == expected_output
print("Output matches expected JSON.")