{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 自定义数字\n",
    "\n",
    "参考：{mod}`numbers`\n",
    "\n",
    "{guilabel}`目标`：\n",
    "\n",
    "1. 创建“数字”这一概念\n",
    "2. 定制数字相关运算"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "int"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from abc import ABC, abstractmethod\n",
    "\n",
    "\n",
    "class Number(ABC):\n",
    "    '''所有的数字都继承于这个类'''\n",
    "    # 如果你只是想检查一个参数 x 是否是一个数字，\n",
    "    # 而不关心是什么类型，可以使用 `isinstance(x, Number)`。\n",
    "    __slots__ = ()\n",
    "    # 具体的数字类型必须提供他们自己的哈希实现\n",
    "    __hash__ = None\n",
    "\n",
    "\n",
    "class Complex(Number):\n",
    "    '''复数定义了在内置复数类型上工作的运算\n",
    "\n",
    "    简而言之，这些是：\n",
    "    转换为 complex、.real、.imag、+、-、*、/、**、abs()、.conjunugate、==、和 !=\n",
    "\n",
    "    如果它被赋予异质的（heterogeneous）参数，并且没有关于它们的特殊知识，它应该返回到内置的 complex 类型。\n",
    "    '''\n",
    "    __slots__ = ()\n",
    "\n",
    "    @abstractmethod\n",
    "    def __complex__(self):\n",
    "        \"\"\"返回一个内置的 complex 实例。为 `complex(self)` 调用。\"\"\"\n",
    "\n",
    "    def __bool__(self):\n",
    "        \"\"\"如果 self !=0，则为真。为 bool(self) 调用。\"\"\"\n",
    "        return self != 0\n",
    "\n",
    "    @property\n",
    "    @abstractmethod\n",
    "    def real(self):\n",
    "        \"\"\"检索这个数字的实数部分。\n",
    "\n",
    "        这应该是 Real 的子类。\n",
    "        \"\"\"\n",
    "        raise NotImplementedError\n",
    "\n",
    "    @property\n",
    "    @abstractmethod\n",
    "    def imag(self):\n",
    "        \"\"\"检索这个数字的虚数部分。\n",
    "\n",
    "        这应该是 Real 的子类。\n",
    "        \"\"\"\n",
    "        raise NotImplementedError\n",
    "\n",
    "    @abstractmethod\n",
    "    def __add__(self, other):\n",
    "        \"\"\"self + other\"\"\"\n",
    "        raise NotImplementedError\n",
    "\n",
    "    @abstractmethod\n",
    "    def __radd__(self, other):\n",
    "        \"\"\"other + self\"\"\"\n",
    "        raise NotImplementedError\n",
    "\n",
    "    @abstractmethod\n",
    "    def __neg__(self):\n",
    "        \"\"\"-self\"\"\"\n",
    "        raise NotImplementedError\n",
    "\n",
    "    @abstractmethod\n",
    "    def __pos__(self):\n",
    "        \"\"\"+self\"\"\"\n",
    "        raise NotImplementedError\n",
    "\n",
    "    def __sub__(self, other):\n",
    "        \"\"\"self - other\"\"\"\n",
    "        return self + -other\n",
    "\n",
    "    def __rsub__(self, other):\n",
    "        \"\"\"other - self\"\"\"\n",
    "        return -self + other\n",
    "\n",
    "    @abstractmethod\n",
    "    def __mul__(self, other):\n",
    "        \"\"\"self * other\"\"\"\n",
    "        raise NotImplementedError\n",
    "\n",
    "    @abstractmethod\n",
    "    def __rmul__(self, other):\n",
    "        \"\"\"other * self\"\"\"\n",
    "        raise NotImplementedError\n",
    "\n",
    "    @abstractmethod\n",
    "    def __truediv__(self, other):\n",
    "        \"\"\"self / other：必要时 promote 为 float。\"\"\"\n",
    "        raise NotImplementedError\n",
    "\n",
    "    @abstractmethod\n",
    "    def __rtruediv__(self, other):\n",
    "        \"\"\"other / self\"\"\"\n",
    "        raise NotImplementedError\n",
    "\n",
    "    @abstractmethod\n",
    "    def __pow__(self, exponent):\n",
    "        \"\"\"self**exponent：必要时 promote 为 float 或者 complex。\"\"\"\n",
    "        raise NotImplementedError\n",
    "\n",
    "    @abstractmethod\n",
    "    def __rpow__(self, base):\n",
    "        \"\"\"base ** self\"\"\"\n",
    "        raise NotImplementedError\n",
    "\n",
    "    @abstractmethod\n",
    "    def __abs__(self):\n",
    "        \"\"\"返回与 0 的 `Real` 距离。为 `abs(self)` 调用。\"\"\"\n",
    "        raise NotImplementedError\n",
    "\n",
    "    @abstractmethod\n",
    "    def conjugate(self):\n",
    "        \"\"\"(x+y*i).conjugate() 返回 (x-y*i)\"\"\"\n",
    "        raise NotImplementedError\n",
    "\n",
    "    @abstractmethod\n",
    "    def __eq__(self, other):\n",
    "        \"\"\"self == other\"\"\"\n",
    "        raise NotImplementedError\n",
    "\n",
    "\n",
    "Complex.register(complex)\n",
    "\n",
    "\n",
    "class Real(Complex):\n",
    "    \"\"\"相对于 Complex，Real 加入了只有实数才能进行的运算。\n",
    "    \n",
    "    简单的说，它们是：转化至 \n",
    "    float、trunc()、divmod()、 %、 <、 <=、 >、 和 >=。\n",
    "\n",
    "    Real 还为派生运算提供了默认值。\n",
    "    \"\"\"\n",
    "\n",
    "    __slots__ = ()\n",
    "\n",
    "    @abstractmethod\n",
    "    def __float__(self):\n",
    "        \"\"\"任何 Real 都可以被转换为原生的 float 对象。\n",
    "\n",
    "        被 float(self) 回调\n",
    "        \"\"\"\n",
    "        raise NotImplementedError\n",
    "\n",
    "    @abstractmethod\n",
    "    def __trunc__(self):\n",
    "        \"\"\"trunc(self): Truncates self to an Integral.\n",
    "\n",
    "        Returns an Integral i such that:\n",
    "          * i>0 iff self>0;\n",
    "          * abs(i) <= abs(self);\n",
    "          * for any Integral j satisfying the first two conditions,\n",
    "            abs(i) >= abs(j) [i.e. i has \"maximal\" abs among those].\n",
    "        i.e. \"truncate towards 0\".\n",
    "        \"\"\"\n",
    "        raise NotImplementedError\n",
    "\n",
    "    @abstractmethod\n",
    "    def __floor__(self):\n",
    "        \"\"\"Finds the greatest Integral <= self.\"\"\"\n",
    "        raise NotImplementedError\n",
    "\n",
    "    @abstractmethod\n",
    "    def __ceil__(self):\n",
    "        \"\"\"Finds the least Integral >= self.\"\"\"\n",
    "        raise NotImplementedError\n",
    "\n",
    "    @abstractmethod\n",
    "    def __round__(self, ndigits=None):\n",
    "        \"\"\"Rounds self to ndigits decimal places, defaulting to 0.\n",
    "\n",
    "        If ndigits is omitted or None, returns an Integral, otherwise\n",
    "        returns a Real. Rounds half toward even.\n",
    "        \"\"\"\n",
    "        raise NotImplementedError\n",
    "\n",
    "    def __divmod__(self, other):\n",
    "        \"\"\"divmod(self, other): The pair (self // other, self % other).\n",
    "\n",
    "        Sometimes this can be computed faster than the pair of\n",
    "        operations.\n",
    "        \"\"\"\n",
    "        return (self // other, self % other)\n",
    "\n",
    "    def __rdivmod__(self, other):\n",
    "        \"\"\"divmod(other, self): The pair (self // other, self % other).\n",
    "\n",
    "        Sometimes this can be computed faster than the pair of\n",
    "        operations.\n",
    "        \"\"\"\n",
    "        return (other // self, other % self)\n",
    "\n",
    "    @abstractmethod\n",
    "    def __floordiv__(self, other):\n",
    "        \"\"\"self // other: The floor() of self/other.\"\"\"\n",
    "        raise NotImplementedError\n",
    "\n",
    "    @abstractmethod\n",
    "    def __rfloordiv__(self, other):\n",
    "        \"\"\"other // self: The floor() of other/self.\"\"\"\n",
    "        raise NotImplementedError\n",
    "\n",
    "    @abstractmethod\n",
    "    def __mod__(self, other):\n",
    "        \"\"\"self % other\"\"\"\n",
    "        raise NotImplementedError\n",
    "\n",
    "    @abstractmethod\n",
    "    def __rmod__(self, other):\n",
    "        \"\"\"other % self\"\"\"\n",
    "        raise NotImplementedError\n",
    "\n",
    "    @abstractmethod\n",
    "    def __lt__(self, other):\n",
    "        \"\"\"self < other\n",
    "\n",
    "        < on Reals defines a total ordering, except perhaps for NaN.\"\"\"\n",
    "        raise NotImplementedError\n",
    "\n",
    "    @abstractmethod\n",
    "    def __le__(self, other):\n",
    "        \"\"\"self <= other\"\"\"\n",
    "        raise NotImplementedError\n",
    "\n",
    "    # Concrete implementations of Complex abstract methods.\n",
    "    def __complex__(self):\n",
    "        \"\"\"complex(self) == complex(float(self), 0)\"\"\"\n",
    "        return complex(float(self))\n",
    "\n",
    "    @property\n",
    "    def real(self):\n",
    "        \"\"\"Real numbers are their real component.\"\"\"\n",
    "        return +self\n",
    "\n",
    "    @property\n",
    "    def imag(self):\n",
    "        \"\"\"Real numbers have no imaginary component.\"\"\"\n",
    "        return 0\n",
    "\n",
    "    def conjugate(self):\n",
    "        \"\"\"Conjugate is a no-op for Reals.\"\"\"\n",
    "        return +self\n",
    "\n",
    "\n",
    "Real.register(float)\n",
    "\n",
    "\n",
    "class Rational(Real):\n",
    "    \"\"\".numerator and .denominator should be in lowest terms.\"\"\"\n",
    "\n",
    "    __slots__ = ()\n",
    "\n",
    "    @property\n",
    "    @abstractmethod\n",
    "    def numerator(self):\n",
    "        raise NotImplementedError\n",
    "\n",
    "    @property\n",
    "    @abstractmethod\n",
    "    def denominator(self):\n",
    "        raise NotImplementedError\n",
    "\n",
    "    # Concrete implementation of Real's conversion to float.\n",
    "    def __float__(self):\n",
    "        \"\"\"float(self) = self.numerator / self.denominator\n",
    "\n",
    "        It's important that this conversion use the integer's \"true\"\n",
    "        division rather than casting one side to float before dividing\n",
    "        so that ratios of huge integers convert without overflowing.\n",
    "\n",
    "        \"\"\"\n",
    "        return self.numerator / self.denominator\n",
    "\n",
    "\n",
    "class Integral(Rational):\n",
    "    \"\"\"Integral adds methods that work on integral numbers.\n",
    "\n",
    "    In short, these are conversion to int, pow with modulus, and the\n",
    "    bit-string operations.\n",
    "    \"\"\"\n",
    "\n",
    "    __slots__ = ()\n",
    "\n",
    "    @abstractmethod\n",
    "    def __int__(self):\n",
    "        \"\"\"int(self)\"\"\"\n",
    "        raise NotImplementedError\n",
    "\n",
    "    def __index__(self):\n",
    "        \"\"\"Called whenever an index is needed, such as in slicing\"\"\"\n",
    "        return int(self)\n",
    "\n",
    "    @abstractmethod\n",
    "    def __pow__(self, exponent, modulus=None):\n",
    "        \"\"\"self ** exponent % modulus, but maybe faster.\n",
    "\n",
    "        Accept the modulus argument if you want to support the\n",
    "        3-argument version of pow(). Raise a TypeError if exponent < 0\n",
    "        or any argument isn't Integral. Otherwise, just implement the\n",
    "        2-argument version described in Complex.\n",
    "        \"\"\"\n",
    "        raise NotImplementedError\n",
    "\n",
    "    @abstractmethod\n",
    "    def __lshift__(self, other):\n",
    "        \"\"\"self << other\"\"\"\n",
    "        raise NotImplementedError\n",
    "\n",
    "    @abstractmethod\n",
    "    def __rlshift__(self, other):\n",
    "        \"\"\"other << self\"\"\"\n",
    "        raise NotImplementedError\n",
    "\n",
    "    @abstractmethod\n",
    "    def __rshift__(self, other):\n",
    "        \"\"\"self >> other\"\"\"\n",
    "        raise NotImplementedError\n",
    "\n",
    "    @abstractmethod\n",
    "    def __rrshift__(self, other):\n",
    "        \"\"\"other >> self\"\"\"\n",
    "        raise NotImplementedError\n",
    "\n",
    "    @abstractmethod\n",
    "    def __and__(self, other):\n",
    "        \"\"\"self & other\"\"\"\n",
    "        raise NotImplementedError\n",
    "\n",
    "    @abstractmethod\n",
    "    def __rand__(self, other):\n",
    "        \"\"\"other & self\"\"\"\n",
    "        raise NotImplementedError\n",
    "\n",
    "    @abstractmethod\n",
    "    def __xor__(self, other):\n",
    "        \"\"\"self ^ other\"\"\"\n",
    "        raise NotImplementedError\n",
    "\n",
    "    @abstractmethod\n",
    "    def __rxor__(self, other):\n",
    "        \"\"\"other ^ self\"\"\"\n",
    "        raise NotImplementedError\n",
    "\n",
    "    @abstractmethod\n",
    "    def __or__(self, other):\n",
    "        \"\"\"self | other\"\"\"\n",
    "        raise NotImplementedError\n",
    "\n",
    "    @abstractmethod\n",
    "    def __ror__(self, other):\n",
    "        \"\"\"other | self\"\"\"\n",
    "        raise NotImplementedError\n",
    "\n",
    "    @abstractmethod\n",
    "    def __invert__(self):\n",
    "        \"\"\"~self\"\"\"\n",
    "        raise NotImplementedError\n",
    "\n",
    "    # Concrete implementations of Rational and Real abstract methods.\n",
    "    def __float__(self):\n",
    "        \"\"\"float(self) == float(int(self))\"\"\"\n",
    "        return float(int(self))\n",
    "\n",
    "    @property\n",
    "    def numerator(self):\n",
    "        \"\"\"Integers are their own numerators.\"\"\"\n",
    "        return +self\n",
    "\n",
    "    @property\n",
    "    def denominator(self):\n",
    "        \"\"\"Integers have a denominator of 1.\"\"\"\n",
    "        return 1\n",
    "\n",
    "\n",
    "Integral.register(int)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": []
  }
 ],
 "metadata": {
  "interpreter": {
   "hash": "217cbd5f9a308b7892384b08237230dd0dcfa951c152faf18c0b07a5660270cf"
  },
  "kernelspec": {
   "display_name": "Python 3.10.0 64-bit ('xpp': conda)",
   "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.10.0"
  },
  "orig_nbformat": 4
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
