Skip to content

Instantly share code, notes, and snippets.

@nhfruchter
Created June 13, 2018 19:04
Show Gist options
  • Save nhfruchter/7a0325b4061b79b32b12a2d71b817359 to your computer and use it in GitHub Desktop.
Save nhfruchter/7a0325b4061b79b32b12a2d71b817359 to your computer and use it in GitHub Desktop.
Dumb stuff with operator overloading
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"from math import inf\n",
"class Node(object):\n",
" MAX_ATTACHMENTS = inf\n",
" \n",
" def __init__(self, label=\"Generic Node\"):\n",
" self.attachments = []\n",
" self.label = label\n",
"\n",
" def _attach(self, other):\n",
" if len(self.attachments) >= self.MAX_ATTACHMENTS:\n",
" raise ValueError(\"{cls} can only be attached to a maximum of {max} objects.\".format(cls=self.__class__, max=self.MAX_ATTACHMENTS))\n",
"\n",
" if other in self.attachments:\n",
" raise Exception(\"Already attached.\")\n",
" \n",
" self.attachments.append(other)\n",
" \n",
" def _detach(self, string, called_from=\"node\"):\n",
" if string not in self.attachments:\n",
" raise ValueError(\"Cannot detach an unattached string.\")\n",
" \n",
" removed_string = self.attachments.pop(string)\n",
"\n",
" if called_from == \"node\":\n",
" removed_string.detach(self, called_from=\"node\")\n",
" \n",
" def relationship(self, string):\n",
" if self == string.start:\n",
" return \"beginning of string\"\n",
" elif self == string.end:\n",
" return \"end of string\" \n",
" else:\n",
" raise ValueError(\"No relationship.\") \n",
"\n",
"class Endpoint(Node):\n",
" MAX_ATTACHMENTS = 1\n",
" \n",
" def __init__(self, label=\"Endpoint\"):\n",
" super(Endpoint, self).__init__(label=label)\n",
"\n",
"class Vertex(Node):\n",
" MAX_ATTACHMENTS = 3\n",
" \n",
" def __init__(self, label=\"Vertex\"):\n",
" super(Vertex, self).__init__(label=label)\n",
" \n",
" \n",
"class String(object):\n",
" @classmethod\n",
" def is_node(self, other):\n",
" if not isinstance(other, Node):\n",
" raise TypeError(\"Strings can only be attached to Node or its subclasses.\")\n",
" else:\n",
" return True\n",
" \n",
" def __init__(self, start=None, end=None):\n",
" self.start = start\n",
" self.end = end\n",
"\n",
" def __radd__(self, other):\n",
" \"\"\"\n",
" Called when String is on the RH of plus sign: <other> + String().\n",
" \n",
" Attachment to beginning of string. \n",
" \"\"\"\n",
" \n",
" assert self.is_node(other)\n",
" self.start = other\n",
" other._attach(self)\n",
" \n",
" def __add__(self, other):\n",
" \"\"\"\n",
" Called when String is on the LH of plus sign: String() + <other>.\n",
"\n",
" Attachment to end of string.\n",
" \"\"\"\n",
" \n",
" assert self.is_node(other)\n",
" self.end = other\n",
" other._attach(self)\n",
"\n",
" def __rsub__(self, other):\n",
" self.detach(self.start)\n",
"\n",
" def __sub__(self, other):\n",
" self.detach(self.end)\n",
"\n",
" def detach(self, node, called_from=\"string\"):\n",
" if self.start == node:\n",
" self.start = None\n",
" if called_from == \"string\":\n",
" node._detach(self)\n",
" elif self.end == node:\n",
" self.end = None\n",
" if called_from == \"string\":\n",
" node._detach(self)\n",
" else:\n",
" raise ValueError(\"Cannot detach unattached node.\")"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"v = Vertex(label=\"v1\")\n",
"e = Endpoint(label=\"e1\")\n",
"s1 = String()"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"v + s1 # Attach to vertex at the start\n",
"s1 + e # And endpoint at the end"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"('v1', 'e1')"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"s1.start.label, s1.end.label"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"([<__main__.String at 0x10a599780>], [<__main__.String at 0x10a599780>])"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"v.attachments, e.attachments "
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [],
"source": [
"s2 = String()"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [
{
"ename": "ValueError",
"evalue": "<class '__main__.Endpoint'> can only be attached to a maximum of 1 objects.",
"output_type": "error",
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)",
"\u001b[0;32m<ipython-input-14-9a252a698327>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0me\u001b[0m \u001b[0;34m+\u001b[0m \u001b[0ms2\u001b[0m \u001b[0;31m# Endpoints can fill up\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
"\u001b[0;32m<ipython-input-3-3520e491b69b>\u001b[0m in \u001b[0;36m__radd__\u001b[0;34m(self, other)\u001b[0m\n\u001b[1;32m 67\u001b[0m \u001b[0;32massert\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mis_node\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mother\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 68\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mstart\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mother\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 69\u001b[0;31m \u001b[0mother\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_attach\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 70\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 71\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0m__add__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mother\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;32m<ipython-input-3-3520e491b69b>\u001b[0m in \u001b[0;36m_attach\u001b[0;34m(self, other)\u001b[0m\n\u001b[1;32m 9\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0m_attach\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mother\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 10\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mlen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mattachments\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m>=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mMAX_ATTACHMENTS\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 11\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mValueError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"{cls} can only be attached to a maximum of {max} objects.\"\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mformat\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mcls\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__class__\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mmax\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mMAX_ATTACHMENTS\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 12\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 13\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mother\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mattachments\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;31mValueError\u001b[0m: <class '__main__.Endpoint'> can only be attached to a maximum of 1 objects."
]
}
],
"source": [
"e + s2 # Endpoints can fill up"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[<__main__.String at 0x10a599780>, <__main__.String at 0x10a5941d0>]"
]
},
"execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"v + s2 # But vertices haven't yet\n",
"v.attachments"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'beginning of string'"
]
},
"execution_count": 16,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"v.relationship(s2)"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"s3 = String()\n",
"s3 + v"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'end of string'"
]
},
"execution_count": 18,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"v.relationship(s3)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.3"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment