diff --git a/.DS_Store b/.DS_Store
new file mode 100644
index 0000000..02ccf12
Binary files /dev/null and b/.DS_Store differ
diff --git a/dev/python-dev.md b/dev/python-dev.md
new file mode 100644
index 0000000..1c5c04b
--- /dev/null
+++ b/dev/python-dev.md
@@ -0,0 +1,1481 @@
+### Python 实战
+
+
+#### 221 自动群发邮件
+
+Python自动群发邮件
+
+```python
+import smtplib
+from email import (header)
+from email.mime import (text, application, multipart)
+import time
+
+def sender_mail():
+ smt_p = smtplib.SMTP()
+ smt_p.connect(host='smtp.qq.com', port=25)
+ sender, password = '113097485@qq.com', "**************"
+ smt_p.login(sender, password)
+ receiver_addresses, count_num = [
+ 'guozhennianhua@163.com', 'xiaoxiazi99@163.com'], 1
+ for email_address in receiver_addresses:
+ try:
+ msg = multipart.MIMEMultipart()
+ msg['From'] = "zhenguo"
+ msg['To'] = email_address
+ msg['subject'] = header.Header('这是邮件主题通知', 'utf-8')
+ msg.attach(text.MIMEText(
+ '这是一封测试邮件,请勿回复本邮件~', 'plain', 'utf-8'))
+ smt_p.sendmail(sender, email_address, msg.as_string())
+ time.sleep(10)
+ print('第%d次发送给%s' % (count_num, email_address))
+ count_num = count_num + 1
+ except Exception as e:
+ print('第%d次给%s发送邮件异常' % (count_num, email_address))
+ continue
+ smt_p.quit()
+
+sender_mail()
+```
+
+
+
+注意:
+发送邮箱是qq邮箱,所以要在qq邮箱中设置开启SMTP服务,设置完成时会生成一个授权码,将这个授权码赋值给文中的`password`变量
+
+#### 222 二分搜索
+
+二分搜索是程序员必备的算法,无论什么场合,都要非常熟练地写出来。
+
+小例子描述:
+在**有序数组**`arr`中,指定区间`[left,right]`范围内,查找元素`x`
+如果不存在,返回`-1`
+
+二分搜索`binarySearch`实现的主逻辑
+
+```python
+def binarySearch(arr, left, right, x):
+ while left <= right:
+
+ mid = int(left + (right - left) / 2); # 找到中间位置。求中点写成(left+right)/2更容易溢出,所以不建议这样写
+
+ # 检查x是否出现在位置mid
+ if arr[mid] == x:
+ print('found %d 在索引位置%d 处' %(x,mid))
+ return mid
+
+ # 假如x更大,则不可能出现在左半部分
+ elif arr[mid] < x:
+ left = mid + 1 #搜索区间变为[mid+1,right]
+ print('区间缩小为[%d,%d]' %(mid+1,right))
+
+ # 同理,假如x更小,则不可能出现在右半部分
+ elif x
+
+```python
+import requests
+from lxml import etree
+import pandas as pd
+import re
+
+url = 'http://www.weather.com.cn/weather1d/101010100.shtml#input'
+with requests.get(url) as res:
+ content = res.content
+ html = etree.HTML(content)
+```
+
+
+
+通过lxml模块提取值
+
+lxml比beautifulsoup解析在某些场合更高效
+
+```python
+location = html.xpath('//*[@id="around"]//a[@target="_blank"]/span/text()')
+temperature = html.xpath('//*[@id="around"]/div/ul/li/a/i/text()')
+```
+
+结果:
+
+```python
+['香河', '涿州', '唐山', '沧州', '天津', '廊坊', '太原', '石家庄', '涿鹿', '张家口', '保定', '三河', '北京孔庙', '北京国子监', '中国地质博物馆', '月坛公
+园', '明城墙遗址公园', '北京市规划展览馆', '什刹海', '南锣鼓巷', '天坛公园', '北海公园', '景山公园', '北京海洋馆']
+
+['11/-5°C', '14/-5°C', '12/-6°C', '12/-5°C', '11/-1°C', '11/-5°C', '8/-7°C', '13/-2°C', '8/-6°C', '5/-9°C', '14/-6°C', '11/-4°C', '13/-3°C'
+, '13/-3°C', '12/-3°C', '12/-3°C', '13/-3°C', '12/-2°C', '12/-3°C', '13/-3°C', '12/-2°C', '12/-2°C', '12/-2°C', '12/-3°C']
+```
+
+
+构造DataFrame对象
+
+```python
+df = pd.DataFrame({'location':location, 'temperature':temperature})
+print('温度列')
+print(df['temperature'])
+```
+
+正则解析温度值
+
+```python
+df['high'] = df['temperature'].apply(lambda x: int(re.match('(-?[0-9]*?)/-?[0-9]*?°C', x).group(1) ) )
+df['low'] = df['temperature'].apply(lambda x: int(re.match('-?[0-9]*?/(-?[0-9]*?)°C', x).group(1) ) )
+print(df)
+```
+
+详细说明子字符创捕获
+
+除了简单地判断是否匹配之外,正则表达式还有提取子串的强大功能。用`()`表示的就是要提取的分组(group)。比如:`^(\d{3})-(\d{3,8})$`分别定义了两个组,可以直接从匹配的字符串中提取出区号和本地号码
+
+```python
+m = re.match(r'^(\d{3})-(\d{3,8})$', '010-12345')
+print(m.group(0))
+print(m.group(1))
+print(m.group(2))
+
+# 010-12345
+# 010
+# 12345
+```
+
+如果正则表达式中定义了组,就可以在`Match`对象上用`group()`方法提取出子串来。
+
+注意到`group(0)`永远是原始字符串,`group(1)`、`group(2)`……表示第1、2、……个子串。
+
+
+最终结果
+
+```kepython
+Name: temperature, dtype: object
+ location temperature high low
+0 香河 11/-5°C 11 -5
+1 涿州 14/-5°C 14 -5
+2 唐山 12/-6°C 12 -6
+3 沧州 12/-5°C 12 -5
+4 天津 11/-1°C 11 -1
+5 廊坊 11/-5°C 11 -5
+6 太原 8/-7°C 8 -7
+7 石家庄 13/-2°C 13 -2
+8 涿鹿 8/-6°C 8 -6
+9 张家口 5/-9°C 5 -9
+10 保定 14/-6°C 14 -6
+11 三河 11/-4°C 11 -4
+12 北京孔庙 13/-3°C 13 -3
+13 北京国子监 13/-3°C 13 -3
+14 中国地质博物馆 12/-3°C 12 -3
+15 月坛公园 12/-3°C 12 -3
+16 明城墙遗址公园 13/-3°C 13 -3
+17 北京市规划展览馆 12/-2°C 12 -2
+18 什刹海 12/-3°C 12 -3
+19 南锣鼓巷 13/-3°C 13 -3
+20 天坛公园 12/-2°C 12 -2
+21 北海公园 12/-2°C 12 -2
+22 景山公园 12/-2°C 12 -2
+23 北京海洋馆 12/-3°C 12 -3
+```
+
+### 十、数据分析
+
+本项目基于Kaggle电影影评数据集,通过这个系列,你将学到如何进行数据探索性分析(EDA),学会使用数据分析利器`pandas`,会用绘图包`pyecharts`,以及EDA时可能遇到的各种实际问题及一些处理技巧。
+
+
+
+本项目需要导入的包:
+
+```python
+import pandas as pd
+import numpy as np
+import matplotlib.pyplot as plt
+from pyecharts.charts import Bar,Grid,Line
+import pyecharts.options as opts
+from pyecharts.globals import ThemeType
+```
+
+#### 1 创建DataFrame
+pandas中一个dataFrame实例:
+```python
+Out[89]:
+ a val
+0 apple1 1.0
+1 apple2 2.0
+2 apple3 3.0
+3 apple4 4.0
+4 apple5 5.0
+```
+
+我们的**目标**是变为如下结构:
+```python
+a apple1 apple2 apple3 apple4 apple5
+0 1.0 2.0 3.0 4.0 5.0
+```
+
+乍看可使用`pivot`,但很难一步到位。
+
+所以另辟蹊径,提供一种简单且好理解的方法:
+
+```python
+In [113]: pd.DataFrame(index=[0],columns=df.a,data=dict(zip(df.a,df.val)))
+Out[113]:
+a apple1 apple2 apple3 apple4 apple5
+0 1.0 2.0 3.0 4.0 5.0
+```
+以上方法是重新创建一个DataFrame,直接把`df.a`所有可能取值作为新dataframe的列,index调整为`[0]`,注意类型必须是数组类型(array-like 或者 Index),两个轴确定后,`data`填充数据域。
+
+```python
+In [116]: dict(zip(df.a,df.val))
+Out[116]: {'apple1': 1.0, 'apple2': 2.0, 'apple3': 3.0, 'apple4': 4.0, 'apple5': 5.0}
+```
+
+
+
+#### 2 导入数据
+数据来自kaggle,共包括三个文件:
+
+1. movies.dat
+2. ratings.dat
+3. users.dat
+
+`movies.dat`包括三个字段:['Movie ID', 'Movie Title', 'Genre']
+
+使用pandas导入此文件:
+
+```python
+import pandas as pd
+
+movies = pd.read_csv('./data/movietweetings/movies.dat', delimiter='::', engine='python', header=None, names = ['Movie ID', 'Movie Title', 'Genre'])
+```
+
+导入后,显示前5行:
+
+```python
+ Movie ID Movie Title \
+0 8 Edison Kinetoscopic Record of a Sneeze (1894)
+1 10 La sortie des usines Lumi猫re (1895)
+2 12 The Arrival of a Train (1896)
+3 25 The Oxford and Cambridge University Boat Race ...
+4 91 Le manoir du diable (1896)
+5 131 Une nuit terrible (1896)
+6 417 Le voyage dans la lune (1902)
+7 439 The Great Train Robbery (1903)
+8 443 Hiawatha, the Messiah of the Ojibway (1903)
+9 628 The Adventures of Dollie (1908)
+ Genre
+0 Documentary|Short
+1 Documentary|Short
+2 Documentary|Short
+3 NaN
+4 Short|Horror
+5 Short|Comedy|Horror
+6 Short|Action|Adventure|Comedy|Fantasy|Sci-Fi
+7 Short|Action|Crime|Western
+8 NaN
+9 Action|Short
+```
+
+
+
+次导入其他两个数据文件
+
+`users.dat`:
+
+```python
+users = pd.read_csv('./data/movietweetings/users.dat', delimiter='::', engine='python', header=None, names = ['User ID', 'Twitter ID'])
+print(users.head())
+```
+
+结果:
+
+```python
+ User ID Twitter ID
+0 1 397291295
+1 2 40501255
+2 3 417333257
+3 4 138805259
+4 5 2452094989
+5 6 391774225
+6 7 47317010
+7 8 84541461
+8 9 2445803544
+9 10 995885060
+```
+
+
+
+`rating.data`:
+
+```python
+ratings = pd.read_csv('./data/movietweetings/ratings.dat', delimiter='::', engine='python', header=None, names = ['User ID', 'Movie ID', 'Rating', 'Rating Timestamp'])
+print(ratings.head())
+```
+
+结果:
+
+```python
+ User ID Movie ID Rating Rating Timestamp
+0 1 111161 10 1373234211
+1 1 117060 7 1373415231
+2 1 120755 6 1373424360
+3 1 317919 6 1373495763
+4 1 454876 10 1373621125
+5 1 790724 8 1374641320
+6 1 882977 8 1372898763
+7 1 1229238 9 1373506523
+8 1 1288558 5 1373154354
+9 1 1300854 8 1377165712
+```
+
+ **read_csv 使用说明**
+
+说明,本次导入`dat`文件使用`pandas.read_csv`函数。
+
+第一个位置参数`./data/movietweetings/ratings.dat` 表示文件的相对路径
+
+第二个关键字参数:`delimiter='::'`,表示文件分隔符使用`::`
+
+后面几个关键字参数分别代表使用的引擎,文件没有表头,所以`header`为`None;`
+
+导入后dataframe的列名使用`names`关键字设置,这个参数大家可以记住,比较有用。
+
+
+
+Kaggle电影数据集第一节,我们使用数据处理利器 `pandas`, 函数`read_csv` 导入给定的三个数据文件。
+
+```python
+import pandas as pd
+
+movies = pd.read_csv('./data/movietweetings/movies.dat', delimiter='::', engine='python', header=None, names = ['Movie ID', 'Movie Title', 'Genre'])
+users = pd.read_csv('./data/movietweetings/users.dat', delimiter='::', engine='python', header=None, names = ['User ID', 'Twitter ID'])
+ratings = pd.read_csv('./data/movietweetings/ratings.dat', delimiter='::', engine='python', header=None, names = ['User ID', 'Movie ID', 'Rating', 'Rating Timestamp'])
+```
+
+用到的`read_csv`,某些重要的参数,如何使用在上一节也有所提到。下面开始数据探索分析(EDA)
+
+> 找出得分前10喜剧(comedy)
+
+
+
+#### 3 处理组合值
+
+表`movies`字段`Genre`表示电影的类型,可能有多个值,分隔符为`|`,取值也可能为`None`.
+
+针对这类字段取值,可使用Pandas中Series提供的`str`做一步转化,**注意它是向量级的**,下一步,如Python原生的`str`类似,使用`contains`判断是否含有`comedy`字符串:
+
+```python
+mask = movies.Genre.str.contains('comedy',case=False,na=False)
+```
+
+注意使用的两个参数:`case`, `na`
+
+case为 False,表示对大小写不敏感;
+na Genre列某个单元格为`NaN`时,我们使用的充填值,此处填充为`False`
+
+返回的`mask`是一维的`Series`,结构与 movies.Genre相同,取值为True 或 False.
+
+观察结果:
+
+```python
+0 False
+1 False
+2 False
+3 False
+4 False
+5 True
+6 True
+7 False
+8 False
+9 False
+Name: Genre, dtype: bool
+
+```
+
+
+ #### 4 访问某列
+
+得到掩码mask后,pandas非常方便地能提取出目标记录:
+
+```python
+comedy = movies[mask]
+comdey_ids = comedy['Movie ID']
+
+```
+
+以上,在pandas中被最频率使用,不再解释。看结果`comedy_ids.head()`:
+
+```python
+5 131
+6 417
+15 2354
+18 3863
+19 4099
+20 4100
+21 4101
+22 4210
+23 4395
+25 4518
+Name: Movie ID, dtype: int64
+
+```
+
+
+
+1-4介绍`数据读入`,`处理组合值`,`索引数据`等, pandas中使用较多的函数,基于Kaggle真实电影影评数据集,最后得到所有`喜剧 ID`:
+
+```python
+5 131
+6 417
+15 2354
+18 3863
+19 4099
+20 4100
+21 4101
+22 4210
+23 4395
+25 4518
+Name: Movie ID, dtype: int64
+
+```
+
+下面继续数据探索之旅~
+
+#### 5 连接两个表
+
+拿到所有喜剧的ID后,要想找出其中平均得分最高的前10喜剧,需要关联另一张表:`ratings`:
+
+再回顾下ratings表结构:
+
+```python
+ User ID Movie ID Rating Rating Timestamp
+0 1 111161 10 1373234211
+1 1 117060 7 1373415231
+2 1 120755 6 1373424360
+3 1 317919 6 1373495763
+4 1 454876 10 1373621125
+5 1 790724 8 1374641320
+6 1 882977 8 1372898763
+7 1 1229238 9 1373506523
+8 1 1288558 5 1373154354
+9 1 1300854 8 1377165712
+
+```
+
+
+pandas 中使用`join`关联两张表,连接字段是`Movie ID`,如果顺其自然这么使用`join`:
+
+```python
+combine = ratings.join(comedy, on='Movie ID', rsuffix='2')
+
+```
+
+左右滑动,查看完整代码
+
+大家可验证这种写法,仔细一看,会发现结果非常诡异。
+
+究其原因,这是pandas join函数使用的一个算是坑点,它在官档中介绍,连接右表时,此处右表是`comedy`,它的`index`要求是连接字段,也就是 `Movie ID`.
+
+左表的index不要求,但是要在参数 `on`中给定。
+
+**以上是要注意的一点**
+
+修改为:
+
+```python
+combine = ratings.join(comedy.set_index('Movie ID'), on='Movie ID')
+print(combine.head(10))
+
+```
+
+以上是OK的写法
+
+观察结果:
+
+```python
+ User ID Movie ID Rating Rating Timestamp Movie Title Genre
+0 1 111161 10 1373234211 NaN NaN
+1 1 117060 7 1373415231 NaN NaN
+2 1 120755 6 1373424360 NaN NaN
+3 1 317919 6 1373495763 NaN NaN
+4 1 454876 10 1373621125 NaN NaN
+5 1 790724 8 1374641320 NaN NaN
+6 1 882977 8 1372898763 NaN NaN
+7 1 1229238 9 1373506523 NaN NaN
+8 1 1288558 5 1373154354 NaN NaN
+9 1 1300854 8 1377165712 NaN NaN
+
+```
+
+Genre列为`NaN`表明,这不是喜剧。需要筛选出此列不为`NaN` 的记录。
+
+#### 6 按列筛选
+
+pandas最方便的地方,就是向量化运算,尽可能减少了for循环的嵌套。
+
+按列筛选这种常见需求,自然可以轻松应对。
+
+为了照顾初次接触 pandas 的朋友,分两步去写:
+
+```python
+mask = pd.notnull(combine['Genre'])
+
+```
+
+结果是一列只含`True 或 False`的值
+
+```python
+result = combine[mask]
+print(result.head())
+
+```
+
+结果中,Genre字段中至少含有一个Comedy字符串,表明验证了我们以上操作是OK的。
+
+```python
+ User ID Movie ID Rating Rating Timestamp Movie Title \
+12 1 1588173 9 1372821281 Warm Bodies (2013)
+13 1 1711425 3 1372604878 21 & Over (2013)
+14 1 2024432 8 1372703553 Identity Thief (2013)
+17 1 2101441 1 1372633473 Spring Breakers (2012)
+28 2 1431045 7 1457733508 Deadpool (2016)
+
+ Genre
+12 Comedy|Horror|Romance
+13 Comedy
+14 Adventure|Comedy|Crime|Drama
+17 Comedy|Crime|Drama
+28 Action|Adventure|Comedy|Sci-Fi
+
+
+```
+
+
+
+截止目前已经求出所有喜剧电影`result`,前5行如下,Genre中都含有`Comedy`字符串:
+```python
+ User ID Movie ID Rating Rating Timestamp Movie Title \
+12 1 1588173 9 1372821281 Warm Bodies (2013)
+13 1 1711425 3 1372604878 21 & Over (2013)
+14 1 2024432 8 1372703553 Identity Thief (2013)
+17 1 2101441 1 1372633473 Spring Breakers (2012)
+28 2 1431045 7 1457733508 Deadpool (2016)
+
+ Genre
+12 Comedy|Horror|Romance
+13 Comedy
+14 Adventure|Comedy|Crime|Drama
+17 Comedy|Crime|Drama
+28 Action|Adventure|Comedy|Sci-Fi
+```
+
+
+
+#### 7 按照Movie ID 分组
+
+result中会有很多观众对同一部电影的打分,所以要求得分前10的喜剧,先按照`Movie ID`分组,然后求出平均值:
+```python
+score_as_movie = result.groupby('Movie ID').mean()
+```
+
+前5行显示如下:
+```python
+ User ID Rating Rating Timestamp
+Movie ID
+131 34861.000000 7.0 1.540639e+09
+417 34121.409091 8.5 1.458680e+09
+2354 6264.000000 8.0 1.456343e+09
+3863 43803.000000 10.0 1.430439e+09
+4099 25084.500000 7.0 1.450323e+09
+```
+
+#### 8 按照电影得分排序
+
+```python
+score_as_movie.sort_values(by='Rating', ascending = False,inplace=True)
+score_as_movie
+```
+前5行显示如下:
+```python
+ User ID Rating Rating Timestamp
+Movie ID
+7134690 30110.0 10.0 1.524974e+09
+416889 1319.0 10.0 1.543320e+09
+57840 23589.0 10.0 1.396802e+09
+5693562 50266.0 10.0 1.511024e+09
+5074 43803.0 10.0 1.428352e+09
+```
+都是满分?这有点奇怪,会不会这些电影都只有几个人评分,甚至只有1个?评分样本个数太少,显然最终的平均分数不具有太强的说服力。
+
+所以,下面要进行每部电影的评分人数统计
+
+#### 9 分组后使用聚合函数
+
+根据`Movie ID`分组后,使用`count`函数统计`每组个数`,只保留count列,最后得到`watchs2`:
+
+```python
+watchs = result.groupby('Movie ID').agg(['count'])
+watchs2 = watchs['Rating']['count']
+```
+打印前20行:
+```python
+print(watchs2.head(20))
+```
+结果:
+```python
+Movie ID
+131 1
+417 22
+2354 1
+3863 1
+4099 2
+4100 1
+4101 1
+4210 1
+4395 1
+4518 1
+4546 2
+4936 2
+5074 1
+5571 1
+6177 1
+6414 3
+6684 1
+6689 1
+7145 1
+7162 2
+Name: count, dtype: int64
+```
+果然,竟然有这么多电影的评论数只有1次!样本个数太少,评论的平均值也就没有什么说服力。
+
+查看`watchs2`一些重要统计量:
+```python
+watchs2.describe()
+```
+结果:
+```python
+count 10740.000000
+mean 20.192086
+std 86.251411
+min 1.000000
+25% 1.000000
+50% 2.000000
+75% 7.000000
+max 1843.000000
+Name: count, dtype: float64
+```
+共有10740部**喜剧**电影被评分,平均打分次数20次,标准差86,75%的电影样本打分次数小于7次,最小1次,最多1843次。
+
+#### 10 频率分布直方图
+
+绘制评论数的频率分布直方图,便于更直观的观察电影被评论的分布情况。上面分析到,75%的电影打分次数小于7次,所以绘制打分次数小于20次的直方图:
+
+```python
+fig = plt.figure(figsize=(12,8))
+histn = plt.hist(watchs2[watchs2 <=19],19,histtype='step')
+plt.scatter([i+1 for i in range(len(histn[0]))],histn[0])
+```
+
+![](./img/20200131094927.jpg)
+
+`histn`元祖表示个数和对应的被分割的区间,查看`histn[0]`:
+```python
+array([4383., 1507., 787., 541., 356., 279., 209., 163., 158.,
+ 118., 114., 90., 104., 81., 80., 73., 62., 65.,
+ 52.])
+```
+```python
+sum(histn[0]) # 9222
+```
+看到电影评论次数1到19次的喜剧电影9222部,共有10740部喜剧电影,大约`86%`的喜剧电影评论次数`小于20次`,有`1518`部电影评论数不小于20次。
+
+我们肯定希望挑选出被评论次数尽可能多的电影,因为难免会有水军和滥竽充数等`异常评论`行为。那么,如何准确的量化最小抽样量呢?
+
+
+
+#### 11 最小抽样量
+
+根据统计学的知识,最小抽样量和Z值、样本方差和样本误差相关,下面给出具体的求解最小样本量的计算方法。
+
+采用如下计算公式:
+
+$$ n = \frac{Z^2\sigma^2}{E^2} $$
+
+
+此处,$Z$ 值取为95%的置信度对应的Z值也就是1.96,样本误差取为均值的2.5%.
+
+根据以上公式,编写下面代码:
+
+```python
+n3 = result.groupby('Movie ID').agg(['count','mean','std'])
+n3r = n3[n3['Rating']['count']>=20]['Rating']
+```
+只计算影评超过20次,且满足最小样本量的电影。计算得到的`n3r`前5行:
+```python
+ count mean std
+Movie ID
+417 22 8.500000 1.263027
+12349 68 8.485294 1.227698
+15324 20 8.350000 1.039990
+15864 51 8.431373 1.374844
+17925 44 8.636364 1.259216
+```
+进一步求出最小样本量:
+```python
+nmin = (1.96**2*n3r['std']**2) / ( (n3r['mean']*0.025)**2 )
+```
+`nmin`前5行:
+```python
+Movie ID
+417 135.712480
+12349 128.671290
+15324 95.349276
+15864 163.434005
+17925 130.668350
+```
+
+筛选出满足最小抽样量的喜剧电影:
+
+```python
+n3s = n3r[ n3r['count'] >= nmin ]
+```
+结果显示如下,因此共有`173`部电影满足最小样本抽样量。
+
+```python
+
+count mean std
+Movie ID
+53604 129 8.635659 1.230714
+57012 207 8.449275 1.537899
+70735 224 8.839286 1.190799
+75686 209 8.095694 1.358885
+88763 296 8.945946 1.026984
+... ... ... ...
+6320628 860 7.966279 1.469924
+6412452 276 7.510870 1.389529
+6662050 22 10.000000 0.000000
+6966692 907 8.673649 1.286455
+7131622 1102 7.851180 1.751500
+173 rows × 3 columns
+```
+
+#### 12 去重和连表
+
+按照平均得分从大到小排序:
+```python
+n3s_sort = n3s.sort_values(by='mean',ascending=False)
+```
+结果:
+```python
+ count mean std
+Movie ID
+6662050 22 10.000000 0.000000
+4921860 48 10.000000 0.000000
+5262972 28 10.000000 0.000000
+5512872 353 9.985836 0.266123
+3863552 199 9.010050 1.163372
+... ... ... ...
+1291150 647 6.327666 1.785968
+2557490 546 6.307692 1.858434
+1478839 120 6.200000 0.728761
+2177771 485 6.150515 1.523922
+1951261 1091 6.083410 1.736127
+173 rows × 3 columns
+```
+仅靠`Movie ID`还是不知道哪些电影,连接`movies`表:
+```python
+ms = movies.drop_duplicates(subset=['Movie ID'])
+ms = ms.set_index('Movie ID')
+n3s_final = n3s_drops.join(ms,on='Movie ID')
+```
+
+#### 13 结果分析
+
+喜剧榜单前50名:
+```python
+Movie Title
+Five Minutes (2017)
+MSG 2 the Messenger (2015)
+Avengers: Age of Ultron Parody (2015)
+Be Somebody (2016)
+Bajrangi Bhaijaan (2015)
+Back to the Future (1985)
+La vita 鐚?bella (1997)
+The Intouchables (2011)
+The Sting (1973)
+Coco (2017)
+Toy Story 3 (2010)
+3 Idiots (2009)
+Green Book (2018)
+Dead Poets Society (1989)
+The Apartment (1960)
+P.K. (2014)
+The Truman Show (1998)
+Am鑼卨ie (2001)
+Inside Out (2015)
+Toy Story 4 (2019)
+Toy Story (1995)
+Finding Nemo (2003)
+Dr. Strangelove or: How I Learned to Stop Worrying and Love the Bomb (1964)
+Home Alone (1990)
+Zootopia (2016)
+Up (2009)
+Monsters, Inc. (2001)
+La La Land (2016)
+Relatos salvajes (2014)
+En man som heter Ove (2015)
+Snatch (2000)
+Lock, Stock and Two Smoking Barrels (1998)
+How to Train Your Dragon 2 (2014)
+As Good as It Gets (1997)
+Guardians of the Galaxy (2014)
+The Grand Budapest Hotel (2014)
+Fantastic Mr. Fox (2009)
+Silver Linings Playbook (2012)
+Sing Street (2016)
+Deadpool (2016)
+Annie Hall (1977)
+Pride (2014)
+In Bruges (2008)
+Big Hero 6 (2014)
+Groundhog Day (1993)
+The Breakfast Club (1985)
+Little Miss Sunshine (2006)
+Deadpool 2 (2018)
+The Terminal (2004)
+```
+
+前10名评论数图:
+
+![](./img/2020013109495711.jpg)
+
+代码:
+```python
+x = n3s_final['Movie Title'][:10].tolist()[::-1]
+y = n3s_final['count'][:10].tolist()[::-1]
+bar = (
+ Bar()
+ .add_xaxis(x)
+ .add_yaxis('评论数',y,category_gap='50%')
+ .reversal_axis()
+ .set_global_opts(title_opts=opts.TitleOpts(title="喜剧电影被评论次数"),
+ toolbox_opts=opts.ToolboxOpts(),)
+)
+grid = (
+ Grid(init_opts=opts.InitOpts(theme=ThemeType.LIGHT))
+ .add(bar, grid_opts=opts.GridOpts(pos_left="30%"))
+)
+grid.render_notebook()
+```
+
+前10名得分图:
+
+![](./img/2020013109500812.jpg)
+
+代码:
+```python
+x = n3s_final['Movie Title'][:10].tolist()[::-1]
+y = n3s_final['mean'][:10].round(3).tolist()[::-1]
+bar = (
+ Bar()
+ .add_xaxis(x)
+ .add_yaxis('平均得分',y,category_gap='50%')
+ .reversal_axis()
+ .set_global_opts(title_opts=opts.TitleOpts(title="喜剧电影平均得分"),
+ xaxis_opts=opts.AxisOpts(min_=8.0,name='平均得分'),
+ toolbox_opts=opts.ToolboxOpts(),)
+)
+grid = (
+ Grid(init_opts=opts.InitOpts(theme=ThemeType.MACARONS))
+ .add(bar, grid_opts=opts.GridOpts(pos_left="30%"))
+)
+grid.render_notebook()
+```
+
+
+
+#### 14 生成哑变量
+
+分类变量的数值化,是指将枚举类变量转化为indicator变量或称dummy变量。
+
+那么什么是`indicator变量`,看看如下例子,A变量解析为:`[1,0,0]`, B解析为:`[0,1,0]`, C解析为:`[0,0,1]`
+```python
+In [8]: s = pd.Series(list('ABCA'))
+In [9]: pd.get_dummies(s)
+Out[9]:
+ A B C
+0 1 0 0
+1 0 1 0
+2 0 0 1
+3 1 0 0
+```
+
+如果输入的字符有4个唯一值,看到字符a被解析为[1,0,0,0],向量长度为4.
+
+```python
+In [5]: s = pd.Series(list('abaccd'))
+In [6]: pd.get_dummies(s)
+Out[6]:
+ a b c d
+0 1 0 0 0
+1 0 1 0 0
+2 1 0 0 0
+3 0 0 1 0
+4 0 0 1 0
+5 0 0 0 1
+```
+
+也就是说dummy向量的长度等于输入字符串中,唯一字符的个数。
+
+#### 15 讨厌的SettingWithCopyWarning!!!
+
+Pandas 处理数据,太好用了,谁用谁知道!
+
+使用过 Pandas 的,几乎都会遇到一个警告:
+
+*SettingWithCopyWarning*
+
+非常烦人!
+
+尤其是刚接触 Pandas 的,完全不理解为什么弹出这么一串:
+
+```python
+d:\source\test\settingwithcopy.py:9: SettingWithCopyWarning:
+A value is trying to be set on a copy of a slice from a DataFrame.
+Try using .loc[row_indexer,col_indexer] = value instead
+
+See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
+```
+
+归根结底,是因为代码中出现`链式操作`...
+
+有人就问了,什么是`链式操作`?
+
+这样的:
+
+```python
+tmp = df[df.a<4]
+tmp['c'] = 200
+```
+
+先记住这个最典型的情况,即可!
+
+有的人就问了:出现这个 Warning, 需要理会它吗?
+
+如果结果不对,当然要理会;如果结果对,不care.
+
+举个例子~~
+
+```python
+import pandas as pd
+
+df = pd.DataFrame({'a':[1,3,5],'b':[4,2,7]},index=['a','b','c'])
+df.loc[df.a<4,'c'] = 100
+print(df)
+print('it\'s ok')
+
+tmp = df[df.a<4]
+tmp['c'] = 200
+print('-----tmp------')
+print(tmp)
+print('-----df-------')
+print(df)
+```
+
+输出结果:
+```python
+ a b c
+a 1 4 100.0
+b 3 2 100.0
+c 5 7 NaN
+it's ok
+d:\source\test\settingwithcopy.py:9: SettingWithCopyWarning:
+A value is trying to be set on a copy of a slice from a DataFrame.
+Try using .loc[row_indexer,col_indexer] = value instead
+
+See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
+ tmp['c'] = 200
+-----tmp------
+ a b c
+a 1 4 200
+b 3 2 200
+-----df-------
+ a b c
+a 1 4 100.0
+b 3 2 100.0
+c 5 7 NaN
+```
+
+it's ok 行后面的发生链式赋值,导致结果错误。因为 tmp 变了,df 没赋上值啊,所以必须理会。
+
+it's ok 行前的是正解。
+
+以上,链式操作尽量避免,如何避免?多使用 `.loc[row_indexer,col_indexer]`,提示告诉我们的~
+
+#### 16 NumPy 数据归一化、分布可视化
+
+仅使用 `NumPy`,下载数据,归一化,使用 `seaborn` 展示数据分布。
+
+**下载数据**
+
+```python
+import numpy as np
+
+url = 'https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data'
+wid = np.genfromtxt(url, delimiter=',', dtype='float', usecols=[1])
+```
+仅提取 `iris` 数据集的第二列 `usecols = [1]`
+
+**展示数据**
+
+```python
+array([3.5, 3. , 3.2, 3.1, 3.6, 3.9, 3.4, 3.4, 2.9, 3.1, 3.7, 3.4, 3. ,
+ 3. , 4. , 4.4, 3.9, 3.5, 3.8, 3.8, 3.4, 3.7, 3.6, 3.3, 3.4, 3. ,
+ 3.4, 3.5, 3.4, 3.2, 3.1, 3.4, 4.1, 4.2, 3.1, 3.2, 3.5, 3.1, 3. ,
+ 3.4, 3.5, 2.3, 3.2, 3.5, 3.8, 3. , 3.8, 3.2, 3.7, 3.3, 3.2, 3.2,
+ 3.1, 2.3, 2.8, 2.8, 3.3, 2.4, 2.9, 2.7, 2. , 3. , 2.2, 2.9, 2.9,
+ 3.1, 3. , 2.7, 2.2, 2.5, 3.2, 2.8, 2.5, 2.8, 2.9, 3. , 2.8, 3. ,
+ 2.9, 2.6, 2.4, 2.4, 2.7, 2.7, 3. , 3.4, 3.1, 2.3, 3. , 2.5, 2.6,
+ 3. , 2.6, 2.3, 2.7, 3. , 2.9, 2.9, 2.5, 2.8, 3.3, 2.7, 3. , 2.9,
+ 3. , 3. , 2.5, 2.9, 2.5, 3.6, 3.2, 2.7, 3. , 2.5, 2.8, 3.2, 3. ,
+ 3.8, 2.6, 2.2, 3.2, 2.8, 2.8, 2.7, 3.3, 3.2, 2.8, 3. , 2.8, 3. ,
+ 2.8, 3.8, 2.8, 2.8, 2.6, 3. , 3.4, 3.1, 3. , 3.1, 3.1, 3.1, 2.7,
+ 3.2, 3.3, 3. , 2.5, 3. , 3.4, 3. ])
+
+```
+
+这是单变量(univariate)长度为 150 的一维 NumPy 数组。
+
+**归一化**
+
+求出最大值、最小值
+```python
+smax = np.max(wid)
+smin = np.min(wid)
+
+In [51]: smax,smin
+Out[51]: (4.4, 2.0)
+````
+归一化公式:
+```python
+s = (wid - smin) / (smax - smin)
+```
+只打印小数点后三位设置:
+```python
+np.set_printoptions(precision=3)
+```
+
+归一化结果:
+```markdown
+array([0.625, 0.417, 0.5 , 0.458, 0.667, 0.792, 0.583, 0.583, 0.375,
+ 0.458, 0.708, 0.583, 0.417, 0.417, 0.833, 1. , 0.792, 0.625,
+ 0.75 , 0.75 , 0.583, 0.708, 0.667, 0.542, 0.583, 0.417, 0.583,
+ 0.625, 0.583, 0.5 , 0.458, 0.583, 0.875, 0.917, 0.458, 0.5 ,
+ 0.625, 0.458, 0.417, 0.583, 0.625, 0.125, 0.5 , 0.625, 0.75 ,
+ 0.417, 0.75 , 0.5 , 0.708, 0.542, 0.5 , 0.5 , 0.458, 0.125,
+ 0.333, 0.333, 0.542, 0.167, 0.375, 0.292, 0. , 0.417, 0.083,
+ 0.375, 0.375, 0.458, 0.417, 0.292, 0.083, 0.208, 0.5 , 0.333,
+ 0.208, 0.333, 0.375, 0.417, 0.333, 0.417, 0.375, 0.25 , 0.167,
+ 0.167, 0.292, 0.292, 0.417, 0.583, 0.458, 0.125, 0.417, 0.208,
+ 0.25 , 0.417, 0.25 , 0.125, 0.292, 0.417, 0.375, 0.375, 0.208,
+ 0.333, 0.542, 0.292, 0.417, 0.375, 0.417, 0.417, 0.208, 0.375,
+ 0.208, 0.667, 0.5 , 0.292, 0.417, 0.208, 0.333, 0.5 , 0.417,
+ 0.75 , 0.25 , 0.083, 0.5 , 0.333, 0.333, 0.292, 0.542, 0.5 ,
+ 0.333, 0.417, 0.333, 0.417, 0.333, 0.75 , 0.333, 0.333, 0.25 ,
+ 0.417, 0.583, 0.458, 0.417, 0.458, 0.458, 0.458, 0.292, 0.5 ,
+ 0.542, 0.417, 0.208, 0.417, 0.583, 0.417])
+```
+
+**分布可视化**
+
+```python
+import seaborn as sns
+sns.distplot(s,kde=False,rug=True)
+```
+频率分布直方图:
+
+
+![](https://imgkr.cn-bj.ufileos.com/49bf5190-429c-4172-a53c-e3f6b66d4e64.png)
+
+
+```python
+sns.distplot(s,hist=True,kde=True,rug=True)
+```
+带高斯密度核函数的直方图:
+
+![](https://imgkr.cn-bj.ufileos.com/4e4a72a5-8f59-4893-b435-e4b57e22a18e.png)
+
+
+
+**分布 fit 图**
+
+拿 `gamma` 分布去 fit :
+```python
+from scipy import stats
+sns.distplot(s, kde=False, fit = stats.gamma)
+```
+
+
+
+![](https://imgkr.cn-bj.ufileos.com/89446755-7420-4f96-97fe-c4e45d0d3dec.png)
+
+
+拿双 `gamma` 去 fit:
+```python
+from scipy import stats
+sns.distplot(s, kde=False, fit = stats.dgamma)
+```
+
+![](https://imgkr.cn-bj.ufileos.com/f2c2a660-5433-4b4f-ad7b-d01da4121319.png)
+
+#### 17 Pandas 使用技巧
+
+对于动辄就几十或几百个 G 的数据,在读取的这么大数据的时候,我们有没有办法随机选取一小部分数据,然后读入内存,快速了解数据和开展 EDA ?
+
+使用 Pandas 的 skiprows 和 概率知识,就能做到。
+
+下面解释具体怎么做。
+
+如下所示,读取某 100 G 大小的 big_data.csv 数据
+
+1) 使用 skiprows 参数,
+
+2) x > 0 确保首行读入,
+
+3) np.random.rand() > 0.01 表示 99% 的数据都会被随机过滤掉
+
+言外之意,只有全部数据的 1% 才有机会选入内存中。
+
+```python
+import pandas as pd
+import numpy as np
+
+df = pd.read_csv("big_data.csv",
+skiprows =
+lambda x: x>0 and np.random.rand() > 0.01)
+
+print("The shape of the df is {}.
+It has been reduced 100 times!".format(df.shape))
+```
+
+使用这种方法,读取的数据量迅速缩减到原来的 1% ,对于迅速展开数据分析有一定的帮助。
+
+### 十一、一步一步掌握Flask web开发
+
+#### 1 Flask版 hello world
+
+Flask是Python轻量级web框架,容易上手,被广大Python开发者所喜爱。
+
+今天我们先从hello world开始,一步一步掌握Flask web开发。例子君是Flask框架的小白,接下来与读者朋友们,一起学习这个对我而言的新框架,大家多多指导。
+
+首先`pip install Flask`,安装Flask,然后import Flask,同时创建一个 `app`
+```python
+from flask import Flask
+
+App = Flask(__name__)
+```
+
+写一个index页的入口函数,返回hello world.
+
+通过装饰器:App.route('/')创建index页的路由或地址,一个`/`表示index页,也就是主页。
+
+```python
+@App.route('/')
+def index():
+ return "hello world"
+```
+
+调用 `index`函数:
+```python
+if __name__ == "__main__":
+ App.run(debug=True)
+```
+
+然后启动,会在console下看到如下启动信息,表明`服务启动成功`。
+```python
+* Debug mode: on
+ * Restarting with stat
+ * Debugger is active!
+ * Debugger PIN: 663-788-611
+ * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
+```
+
+ 接下来,打开一个网页,相当于启动客户端,并在Url栏中输入:`http://127.0.0.1:5000/`,看到页面上答应出`hello world`,证明服务访问成功。
+
+ 同时在服务端后台看到如下信息,表示处理一次来自客户端的`get`请求。
+ ```python
+ 27.0.0.1 - - [03/Feb/2020 21:26:50] "GET / HTTP/1.1" 200 -
+ ```
+
+ 以上就是flask的hello world 版
+
+#### 2 Flask之数据入库操作
+
+数据持久化就是将数据写入到数据库存储的过程。
+
+本例子使用`sqlite3`数据库。
+
+1)导入`sqlite3`,未安装前使用命令`pip install sqlite3`
+
+创建一个`py`文件:`sqlite3_started.py`,并写下第一行代码:
+```python
+import sqlite3
+```
+2)手动创建一个数据库实例`db`, 命名`test.db`
+
+3)创建与数据库实例`test.db`的连接:
+```python
+conn = sqlite3.connect("test.db")
+```
+
+4)拿到连接`conn`的cursor
+```python
+c = conn.cursor()
+```
+
+5)创建第一张表`books`
+
+共有四个字段:`id`,`sort`,`name`,`price`,类型分别为:`int`,`int`,`text`,`real`. 其中`id`为`primary key`. 主键的取值必须是唯一的(`unique`),否则会报错。
+
+
+```python
+c.execute('''CREATE TABLE books
+ (id int primary key,
+ sort int,
+ name text,
+ price real)''')
+```
+第一次执行上面语句,表`books`创建完成。当再次执行时,就会报`重复建表`的错误。需要优化脚本,检查表是否存在`IF NOT EXISTS books`,不存在再创建:
+```python
+c.execute('''CREATE TABLE IF NOT EXISTS books
+ (id int primary key,
+ sort int,
+ name text,
+ price real)''')
+```
+
+6)插入一行记录
+
+共为4个字段赋值
+
+```python
+c.execute('''INSERT INTO books VALUES
+ (1,
+ 1,
+ 'computer science',
+ 39.0)''')
+```
+
+7)一次插入多行记录
+
+先创建一个list:`books`,使用`executemany`一次插入多行。
+```python
+books = [(2, 2, 'Cook book', 68),
+ (3, 2, 'Python intro', 89),
+ (4, 3, 'machine learning', 59),
+ ]
+
+
+c.executemany('INSERT INTO books VALUES (?, ?, ?, ?)', books)
+```
+
+8)提交
+
+提交后才会真正生效,写入到数据库
+
+```python
+conn.commit()
+```
+
+9)关闭期初建立的连接conn
+
+务必记住手动关闭,否则会出现内存泄漏
+```python
+conn.close()
+print('Done')
+```
+
+10)查看结果
+例子君使用`vs code`,在扩展库中选择:`SQLite`安装。
+
+![image-20200208211721377](./img/image-20200208211721377.png)
+
+新建一个`sq`文件:`a.sql`,内容如下:
+
+```sql
+SELECT * from books
+```
+右键`run query`,得到表`books`插入的4行记录可视化图:
+
+![image-20200208211806853](./img/image-20200208211806853.png)
+
+以上十步就是sqlite3写入数据库的主要步骤,作为Flask系列的第二篇,为后面的前端讲解打下基础。
+
+#### 3 Flask各层调用关系
+
+这篇介绍Flask和B/S模式,即浏览器/服务器模式,是接下来快速理解Flask代码的关键理论篇:**理解Views、models和渲染模板层的调用关系**。
+
+1) 发出请求
+
+当我们在浏览器地址栏中输入某个地址,按回车后,完成第一步。
+
+2) 视图层 views接收1)步发出的请求,Flask中使用解释器的方式处理这个求情,实例代码如下,它通常涉及到调用models层和模板文件层
+
+```python
+@main_blue.route('/', methods=['GET', 'POST'])
+def index():
+ form = TestForm()
+ print('test')
+```
+
+3) models层会负责创建数据模型,执行CRUD操作
+
+4) 模板文件层处理html模板
+
+5) 组合后返回html
+
+6) models层和html模板组合后返回给views层
+
+7)最后views层响应并渲染到浏览器页面,我们就能看到请求的页面。
+
+完整过程图如下所示:
+
+![image-20200211152007983](./img/web1.png)
+
+读者朋友们,如果你和例子君一样都是初学Flask编程,需要好好理解上面的过程。理解这些对于接下来的编程会有一定的理论指导,方向性指导价值。
+
+### Python 问答
+
+#### Python 如何生成二维码?
+
+
+
+
+
+## qrcode
+
+今天先来解答如何生成二维码。Python的`qrcode`包支持生成二维码。
+
+用法也很简单:
+
+```python
+import qrcode
+
+# 二维码内容
+data = "http://www.zglg.work/wp-content/uploads/2020/10/image-3.png"
+# 生成二维码
+img = qrcode.make(data=data)
+# 直接显示二维码
+img.show()
+# 保存二维码为文件
+img.save("我的微信.jpg")
+```
+
+生成的二维码如下:
+
+![](https://imgkr2.cn-bj.ufileos.com/f0b08c53-0107-483b-bbe5-072bebc58e8d.png?UCloudPublicKey=TOKEN_8d8b72be-579a-4e83-bfd0-5f6ce1546f13&Signature=rVtaeBWhzLPPq%252BFCVtiOv6rS0tI%253D&Expires=1603544615)
+
+
+大家微信扫描后,会出现我的二维码。
+
+另外,还可以设置二维码的颜色等样式:
+
+```python
+import qrcode
+
+# 实例化二维码生成类
+qr = qrcode.QRCode(border=2)
+# 设置二维码数据
+data = "http://www.zglg.work/wp-content/uploads/2020/10/image-3.png"
+qr.add_data(data=data)
+# 启用二维码颜色设置
+qr.make(fit=True)
+img = qr.make_image(fill_color="orange", back_color="white")
+
+# 显示二维码
+img.show()
+```
+
+生成一个orange的二维码:
+
+![](https://imgkr2.cn-bj.ufileos.com/cbd26fd8-27cf-4630-935f-6896822ce483.png?UCloudPublicKey=TOKEN_8d8b72be-579a-4e83-bfd0-5f6ce1546f13&Signature=uy1r24x%252Fp5QpI5Wy10Ebdaz%252BpLM%253D&Expires=1603544681)
+
+更多样式,大家可以自己去玩耍。
+
+## Python小项目:句子KWIC显示
+
+上下文关键字(KWIC, Key Word In Context)是最常见的多行协调显示格式。
+
+此小项目描述:输入一系列句子,给定一个给定单词,每个句子中至少会出现一次给定单词。目标输出,给定单词按照KWIC显示,KWIC显示的基本要求:待查询单词居中,前面`pre`序列右对齐,后面`post`序列左对齐,待查询单词前和后长度相等,若输入句子无法满足要求,用空格填充。
+
+输入参数:输入句子sentences, 待查询单词selword, 滑动窗口长度`window_len`
+
+举例,输入如下六个句子,给定单词`secure`,输出如下字符串:
+
+```python
+ pre keyword post
+
+ welfare , and secure the blessings of
+ nations , and secured immortal glory with
+ , and shall secure to you the
+ cherished . To secure us against these
+ defense as to secure our cities and
+ I can to secure economy and fidelity
+```
+
+请补充实现下面函数:
+
+```python
+def kwic(sentences: List[str], selword: str, window_len: int) -> str:
+ """
+ :type: sentences: input sentences
+ :type: selword: selected word
+ :type: window_len: window length
+ """
+```
+
+更多KWIC显示参考如下:
+
+http://dep.chs.nihon-u.ac.jp/english_lang/tukamoto/kwic_e.html
+
+完整代码已经公布在:http://www.zglg.work/Python-20-topics/python-project1-kwic/
+![image](https://user-images.githubusercontent.com/20391209/123213609-c494dc00-d4f8-11eb-84d6-4d8caabb44f7.png)
+![image](https://user-images.githubusercontent.com/20391209/123213901-26eddc80-d4f9-11eb-96cd-d3518005c4df.png)
+
diff --git a/md/198.md b/md/198.md
index 566f643..1a42378 100644
--- a/md/198.md
+++ b/md/198.md
@@ -6,6 +6,23 @@
@version
@date 2020/04/05
```
-
+## 198 常见算术运算
-
[上一个例子](197.md) [下一个例子](199.md)
\ No newline at end of file
+```python
+x, y = 3, 2
+print(x + y) # = 5
+print(x - y) # = 1
+print(x * y) # = 6
+print(x / y) # = 1.5
+print(x // y) # = 1
+print(x % y) # = 1
+print(-x) # = -3
+print(abs(-x)) # = 3
+print(int(3.9)) # = 3
+print(float(x)) # = 3.0
+print(x ** y) # = 9
+```
+
+大多数操作符都是不言自明的。注意,`//`运算符执行整数除法。结果是一个向下舍入的整数值(例如,3//2==1)
+
+[上一个例子](197.md) [下一个例子](199.md)