{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Python 基本数据类型\n",
    "\n",
    "Python 内置了一些基本数据类型，极大的方便描述的任务。\n",
    "\n",
    "Python 中带有关键字的结构，用于表达特定的语义，被称为 **语句**。\n",
    "\n",
    "本节主要探讨 {token}`表达式语句 <python-grammar:expression_stmt>` 与 {token}`赋值语句 <python-grammar:assignment_stmt>`。\n",
    "\n",
    "Python 的 {term}`表达式 <expression>` 表示那些可以被求值的对象。换句话说，一个表达式就是表达元素例如字面值、名称、属性访问、运算符或调用，它们最终都会返回一个值。本文主要介绍 Python 基本数据类型所代表的表达式。\n",
    "\n",
    "赋值语句用于将名称（重）绑定到特定值，以及修改属性或可变对象的成员项：\n",
    "\n",
    "```md\n",
    "标识符（或者标识符列表）= 表达式\n",
    "```\n",
    "\n",
    "此时的标识符一般被称为 `变量`。\n",
    "\n",
    "## 标识符\n",
    "\n",
    "{ref}`标识符 <identifiers>` （也称为 **名称**）是由特定的 Unicode 字符（包含英文、汉字等，且英文字母区分大小写）、（十进制）数字和下划线组成，但不能以数字作为开头。\n",
    "\n",
    "示例："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "长度 = 100 # 单位 m\n",
    "宽度 = 400 # 单位 m\n",
    "面积 = 长度 * 宽度 # 单位 m^2\n",
    "面积"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "可以看出：标识符大大地简化了表达丰富语义的过程。\n",
    "\n",
    "```{warning}\n",
    "如果变量未定义（即，未赋值），使用该变量会提示错误（在 Python 中被称为 “异常”）：\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "小马"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 数字\n",
    "\n",
    "数字字面值与运算符 `+`（正号，一般被省略）、`-`（负号） 组成了数学中的数字（名称为 {class}`numbers.Number`）。按照数域范围分为：整型（名称为 {class}`numbers.Integral` 表示）、分数型（名称为 {class}`numbers.Rational`）、浮点型（名称为 {class}`numbers.Real` 表示）以及复数型（名称为 {class}`numbers.Complex` 表示）。整型、分数型、浮点型以及复数型支持数学运算。\n",
    "\n",
    "### 数学运算\n",
    "\n",
    "Python 提供有基本的数学运算：\n",
    "\n",
    "1. `+`（加法）、`-`（减法）、`*`（乘法）、`/`（除法）、`//`（向下取整除法）、`%`（求余）、`**`（乘方）；\n",
    "2. 使用 `()` 分组表达式，用于改变运算的优先级。\n",
    "\n",
    "可看一些例子（以整数为例）："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "76"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "27 + 49 # 整数加法"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "99"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "100 - 1 # 整数减法"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "135"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "45 * 3 # 整数乘法"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "12.5"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "75 / 6 # 整数除法"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "5.0"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "75 / 15 # 除法返回的值总是浮点数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "50"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "(3 + 7) * 5 # 使用 () 分组表达式"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(10, 10, 11)"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "50 // 5, 53 // 5, 57 // 5 # 向下取整"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "73 % 9 # 求取余数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1024"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "2 ** 10 # 乘方"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 复数\n",
    "\n",
    "看看 Python 是如何表达 {dfn}`复数` 的。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(3+5j)"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "7j # 纯虚数字面量\n",
    "3 + 5j # 复数字面量"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "复数的运算："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "((10+5j),\n",
       " (-4+3j),\n",
       " (17+31j),\n",
       " (0.49999999999999994+0.5j),\n",
       " (-7542.58226836217+29973.54852192689j))"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 定义复数变量\n",
    "a = 3 + 4j \n",
    "b = 7 + 1j\n",
    "a + b, a - b, a * b, a / b, a ** b"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 对象的属性、方法以及函数\n",
    "\n",
    "由于 Python 一切皆是对象，故而每个对象都可能绑定了一些属性（通过 `.` 获取其值）、{term}`方法 <method>` 以及 {term}`函数 <function>`。\n",
    "\n",
    "比如，复数 $z$ 有一些属性值："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "6.0"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "z = 6 + 8j\n",
    "\n",
    "z.real # 复数的实部"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "8.0"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "z.imag # 复数的虚部"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**方法** 可以理解为对象自有的行为，一般带有 `(参数列表)` 调用其行为。比如，复数 $z$ 有一个求取共轭复数的**方法**："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(3-4j)"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a.conjugate()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Python 内置了许多函数用于处理对象。**函数** 可以理解为通用的行为，一般带有 `(参数列表)` 调用其行为。\n",
    "\n",
    "比如，求取复数 $z$ 的模："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "10.0"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "abs(z)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 序列\n",
    "\n",
    "本次仅仅讨论几个常用的序列：字符串（不可变）、元组（不可变）和列表（可变）。\n",
    "\n",
    "### 字符串\n",
    "\n",
    "Python 使用 **字符串** 记录对象的“语义”信息。字符串通常使用双引号、单引号等表示。如："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [],
   "source": [
    "晓明 = '小马'\n",
    "say = \"小马，说 '你好！'\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "字符串可以使用函数 {func}`print` 显示信息："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "小马\n"
     ]
    }
   ],
   "source": [
    "print(晓明)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "小马，说 '你好！'\n"
     ]
    }
   ],
   "source": [
    "print(say)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "可能会有一些特殊字符，需要 `\\` 进行转义："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'你好\\n世界'"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ss = '你好\\n世界'\n",
    "ss # 直接显示，则换行符 `\\n` 没有被转义"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "你好\n",
      "世界\n"
     ]
    }
   ],
   "source": [
    "# 使用 print 显示转义\n",
    "print(ss)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "还有一种情况，你不想将一些转义符号转义，可以使用原始字符串 `r\"...\"` 模式："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "你好\\n世界\n"
     ]
    }
   ],
   "source": [
    "st = r'你好\\n世界'\n",
    "print(st) # 转义被忽略"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "其实原始字符串，等同于将 `\\` “逃逸”："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'你好\\\\n世界'"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "st"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "有时，想要在字符串中嵌入变量，可以使用 `f\"...{变量}\"`（被称为 **格式字符串**，此类字符串是 **表达式**，而不是常量）："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "小小的身高是 160\n"
     ]
    }
   ],
   "source": [
    "h = 160 # 身高\n",
    "小小 = f\"小小的身高是 {h}\"\n",
    "print(小小)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 字符串的运算\n",
    "\n",
    "字符串也支持一些特殊的运算。比如，拼接："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'Aa'"
      ]
     },
     "execution_count": 28,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "'A' 'a'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'Aa'"
      ]
     },
     "execution_count": 29,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "'A' + 'a'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'AAAAA'"
      ]
     },
     "execution_count": 30,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "'A' * 5"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "如果字符串很长很长，可以使用如下方法拼接（以空白符分隔的多个相邻字符串或字节串字面值，可用不同引号标注，等同于合并操作）："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'abc'"
      ]
     },
     "execution_count": 31,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "('a'\n",
    "'b'\n",
    "'c')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "还有一种特殊的字符串，叫做文档字符串，使用 `'''...'''` 表示："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "iter\n",
      "djkf \n",
      "fkd\n",
      "\n"
     ]
    }
   ],
   "source": [
    "a = '''iter\n",
    "djkf \n",
    "fkd\n",
    "'''\n",
    "\n",
    "print(a)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "可以看出，字符串是自动换行的。此类字符串常用于注释代码块。\n",
    "\n",
    "### 列表 & 元组\n",
    "\n",
    "使用 `[...]` 包裹的 Python 类型称为 **列表**；使用 `(...)` 包裹的 Python 类型称为 **元组**。不同项使用 `,` 隔开。\n",
    "\n",
    "例如："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "('春', '夏', '秋', '冬')\n",
      "['小猫1', '小猫2']\n"
     ]
    }
   ],
   "source": [
    "四季 = ('春', '夏', '秋', '冬') # 元组\n",
    "猫屋 = ['小猫1', '小猫2'] # 列表\n",
    "print(四季)\n",
    "print(猫屋)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```{hint}\n",
    "元组的定义真正起作用的是 `,`。\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(2, 4, 's')"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "2, 4, 's' # 这也是元组"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 集合\n",
    "\n",
    "集合\n",
    ":   此类对象表示由不重复且不可变对象组成的无序且有限的集合。因此它们不能通过下标来索引。但是它们可被迭代，也可用内置函数 {func}`len` 返回集合中的项数。集合常见的用处是快速成员检测，去除序列中的重复项，以及进行交、并、差和对称差等数学运算。\n",
    "\n",
    "集合分为两类：\n",
    "\n",
    "- 可变集合：{class}`set`\n",
    "- 不可变集合：{class}`frozenset`\n",
    "\n",
    "例如："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'a', 'e', 'r', 'w'}"
      ]
     },
     "execution_count": 34,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "字母集 = {'a', 'w', 'a', 'e', 'r'} \n",
    "# 等价于 字母集 = set('a', 'w', 'a', 'e', 'r')\n",
    "字母集"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "可以看到，已经自动去除重复项。\n",
    "\n",
    "## 字典\n",
    "\n",
    "Python 使用字典表示对象之间的关系。表示方法有：\n",
    "\n",
    "1. `{key: value, key1: value2, ...}` 键值对的形式\n",
    "2. {class}`dict`(key=value, key1=value2)\n",
    "\n",
    "例如："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'a': 'A', 'b': 'B'}"
      ]
     },
     "execution_count": 35,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "字母表 = {\n",
    "    'a': 'A',\n",
    "    'b': 'B'\n",
    "}\n",
    "\n",
    "字母表2 = dict(a='A', b='B')\n",
    "\n",
    "字母表"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 对象的编号与类型\n",
    "\n",
    "一个 Python 对象的编号和类型是唯一的，可以分别使用 {func}`id` 与 {class}`type` 获取其值。\n",
    "\n",
    "比如："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [],
   "source": [
    "h = 450 # 高度"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1778503186416"
      ]
     },
     "execution_count": 37,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "地址 = id(h) # 获取标识符 h 的所在地址，即编号\n",
    "地址"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "int"
      ]
     },
     "execution_count": 38,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "类型 = type(h) # h 的类型是整数 int\n",
    "类型"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<iframe id=\"Python\"\n",
    "    title=\"Python 基本数据类型与变量\"\n",
    "    width=\"100%\"\n",
    "    height=\"500\"\n",
    "    src=\"https://developer.hs.net/thread/1600?nav=course\">\n",
    "</iframe>\n"
   ]
  }
 ],
 "metadata": {
  "interpreter": {
   "hash": "31f2aee4e71d21fbe5cf8b01ff0e069b9275f58929596ceb00d14d90e3e16cd6"
  },
  "kernelspec": {
   "display_name": "Python 3.8.10 64-bit",
   "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"
  },
  "orig_nbformat": 4
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
