{ "cells": [ { "cell_type": "markdown", "id": "07cb0e9d", "metadata": {}, "source": [ "### FreeObject\n", "\n", "#### What is FreeObject?\n", "\n", "Object 支持 . 操作来引用公共成员,Map 支持 [] 来引用字段。现定义一个类,其对象支持从 map 构造,可同时通过 [] 和 . 操作来引用字段成员。这个对象暂时称之为 FreeObject。\n", "\n", "FreeObject 是自动递归的,即自动支持 Object.a.b 和 Object['a']['b'] 的操作\n" ] }, { "cell_type": "code", "execution_count": 30, "id": "4657c72e", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "free\n", "free\n", "None\n", "None\n" ] } ], "source": [ "class FreeObject:\n", " def __init__(self, dct={}):\n", " self.__dict__.update(dct)\n", " self.name = 'free'\n", " \n", " def __getitem__(self, name):\n", " return self.__dict__.get(name)\n", " \n", " def __getattr__(self, name):\n", " return self.__dict__.get(name)\n", "\n", "# test\n", "fo = FreeObject({'b': 20})\n", "print(fo.name)\n", "print(fo['name'])\n", "#\n", "print(fo.a) # None\n", "print(fo['a']) # None" ] }, { "cell_type": "markdown", "id": "e3784c5c", "metadata": {}, "source": [ "#### V1\n", "\n", "上面的实现非常简单,但有两个问题\n", "1. 它仅支持平面结构,而不支持嵌套\n", "```python\n", "print(fo.a.c) # 要求 fo.a 返回的也必须是一个 FreeObject 对象\n", "```\n", "2. __init__() 之外,也可以任意的追加实例的属性,这可能把结构弄的很混乱\n", "```python\n", "fo.not_exists = 'exists'\n", "print(fo.not_exists) # 在构造函数之外添加了属性\n", "```\n" ] }, { "cell_type": "code", "execution_count": 47, "id": "52eee17a", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "passed\n", "passed\n", "{'a': 1, 'b': <__main__.FreeObject object at 0x7f467b9b6100>}\n", "None\n", "None\n", "exists\n" ] } ], "source": [ "class FreeObject:\n", " def __init__(self, dct={}):\n", " self.__recursive_init(dct)\n", " \n", " def __recursive_init(self, dct={}):\n", " '''\n", " 递归初始化 FreeObject\n", " '''\n", " self.__dict__.update(dct)\n", " for k, v in dct.items():\n", " if type(v) is dict:\n", " self.__dict__[k] = FreeObject(v)\n", " \n", " def __getitem__(self, name):\n", " return self.__dict__.get(name)\n", " \n", " def __getattr__(self, name):\n", " return self.__dict__.get(name)\n", " \n", " def __setattr__(self, name, value):\n", " pass\n", " \n", " def __setitem__(self, name, value):\n", " pass\n", "\n", "fo = FreeObject({'a': 1, 'b': {'c': 1, 'd': {'test': 'passed'}}})\n", "# issue1\n", "print(fo.b.d.test)\n", "print(fo['b']['d']['test'])\n", "print(fo.__dict__)\n", "\n", "# issue2\n", "fo.not_exists = 'exists'\n", "print(fo.not_exists)\n", "fo['not_exists'] = 'exists'\n", "print(fo.not_exists)\n", "\n", "# new issues\n", "fo.__dict__['not_exists'] = 'exists'\n", "print(fo.not_exists)" ] }, { "cell_type": "markdown", "id": "3dfc53df", "metadata": {}, "source": [ "### v2\n", "\n", "上面新的实现中,初步解决了 V1 中的两个问题。但还存在直接访问修改实例的 __dict__ 属性的方法来侵入对象内部。\n", "\n" ] }, { "cell_type": "markdown", "id": "7815e12f", "metadata": {}, "source": [ "**To be Continue**" ] }, { "cell_type": "code", "execution_count": null, "id": "ccf518a7", "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "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.9.7" } }, "nbformat": 4, "nbformat_minor": 5 }