├── 1 python基础语法.ipynb ├── 1 python基础语法.pdf ├── 2 pandas用法.ipynb ├── 2 pandas用法.pdf ├── 3 Numpy计算.ipynb ├── 3 Numpy计算.pdf ├── 4 文件读取与文件合并.ipynb ├── 4 文件读取与文件合并.pdf ├── 5 python 正则表达式.ipynb ├── 5 python 正则表达式.pdf ├── 6 日期、时序函数的生成与转化.ipynb ├── 6 日期、时序函数的生成与转化.pdf ├── 7 Python 类与对象.ipynb ├── 7 Python 类与对象.pdf ├── 8 Python 装饰器.ipynb ├── 8 Python 装饰器.pdf ├── 9 绘图可视化部分.ipynb ├── 9 绘图可视化部分.pdf └── README.md /1 python基础语法.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "source": [ 6 | "# 第一章 python基础应用\n", 7 | "\n", 8 | " #本章主要介绍一些在python的基础应用,主要从以下几个方面来介绍:\n", 9 | " \n", 10 | "一、 python基础路径\n", 11 | " * 路径操作\n", 12 | " * 模块引用\n", 13 | " \n", 14 | "二、 python常用语法结构\n", 15 | " * 运算逻辑符\n", 16 | " * 控制流语句 \n", 17 | " * 常用关键字\n", 18 | " * 其他python输入及格式化输出\n", 19 | " * lambda函数\n", 20 | " \n", 21 | "三、 python常用类型/序列函数\n", 22 | " * 列表\n", 23 | " * 字典\n", 24 | " * tuple\n", 25 | " * 元组\n", 26 | " * 常用序列函数\n" 27 | ], 28 | "metadata": {} 29 | }, 30 | { 31 | "cell_type": "markdown", 32 | "source": [ 33 | "## 1.python基础路径\n", 34 | "### 1.1 路径操作" 35 | ], 36 | "metadata": {} 37 | }, 38 | { 39 | "cell_type": "markdown", 40 | "source": [ 41 | "### 1.1.1 绝对路径和相对路径\n", 42 | "文件路径就是文件在电脑中的位置,表示文件路径的方式有两种,相对路径和绝对路径。其中,相对路径就是相对于当前文件的路径,它相对于程序的当前工作目录;本地路径是指文件在硬盘上真正存在的路径,总是从根文件夹开始。\n", 43 | "\n", 44 | "在表示路径中我们常用点(.)和点点(..)文件夹,它们不是真正的文件夹,而是可以在路径中使用的特殊名称。单个的句点(“点”)用作文件夹目名称时,是“这个目录”的缩写。两个句点(“点点”)意思是父文件夹。" 45 | ], 46 | "metadata": {} 47 | }, 48 | { 49 | "cell_type": "raw", 50 | "source": [], 51 | "metadata": {} 52 | }, 53 | { 54 | "cell_type": "code", 55 | "source": [ 56 | "##处理绝对路径和相对路径\n", 57 | "import os\n", 58 | "print(os.path.abspath('.'))#返回一个相对路径的绝对路径\n", 59 | "print(os.path.abspath('.\\data'))#返回一个相对路径的绝对路径\n", 60 | "#检查一个路径是否绝对路径,如果是则返回true\n", 61 | "print(os.path.isabs('.'))\n", 62 | "print(os.path.isabs(os.path.abspath('.')))" 63 | ], 64 | "outputs": [ 65 | { 66 | "output_type": "stream", 67 | "name": "stdout", 68 | "text": [ 69 | "F:\\jupyter\\浩彬分享的代码\n", 70 | "F:\\jupyter\\浩彬分享的代码\\data\n", 71 | "False\n", 72 | "True\n" 73 | ] 74 | } 75 | ], 76 | "execution_count": 2, 77 | "metadata": {} 78 | }, 79 | { 80 | "cell_type": "code", 81 | "source": [ 82 | "print(os.path.abspath('.'))" 83 | ], 84 | "outputs": [ 85 | { 86 | "output_type": "stream", 87 | "name": "stdout", 88 | "text": [ 89 | "F:\\jupyter\\浩彬分享的代码\n" 90 | ] 91 | } 92 | ], 93 | "execution_count": 3, 94 | "metadata": {} 95 | }, 96 | { 97 | "cell_type": "code", 98 | "source": [], 99 | "outputs": [], 100 | "execution_count": 5, 101 | "metadata": { 102 | "collapsed": true 103 | } 104 | }, 105 | { 106 | "cell_type": "markdown", 107 | "source": [ 108 | "### 1.1.2 路径的生成与拼接" 109 | ], 110 | "metadata": {} 111 | }, 112 | { 113 | "cell_type": "code", 114 | "source": [ 115 | "#使用os.path.join生成路径\n", 116 | "from pathlib import Path\n", 117 | "home = \"D:\\\\jupyter\"\n", 118 | "data_folder=os.path.join(home,\"python\",\"Code\")\n", 119 | "data_filename = os.path.join(data_folder,\"Chapter 2\",\"ionosphere.data\")\n", 120 | "print(data_filename)" 121 | ], 122 | "outputs": [ 123 | { 124 | "output_type": "stream", 125 | "name": "stdout", 126 | "text": [ 127 | "D:\\jupyter\\python\\Code\\Chapter 2\\ionosphere.data\n" 128 | ] 129 | } 130 | ], 131 | "execution_count": 7, 132 | "metadata": {} 133 | }, 134 | { 135 | "cell_type": "code", 136 | "source": [ 137 | "print('1:',Path()) #取当前路径\n", 138 | "print('2:',Path('a','b','c/d')) #字符合成\n", 139 | "print('3:',Path('/etc')) #直接写入绝对路径" 140 | ], 141 | "outputs": [ 142 | { 143 | "output_type": "stream", 144 | "name": "stdout", 145 | "text": [ 146 | "1: .\n", 147 | "2: a\\b\\c\\d\n", 148 | "3: \\etc\n" 149 | ] 150 | } 151 | ], 152 | "execution_count": 6, 153 | "metadata": {} 154 | }, 155 | { 156 | "cell_type": "markdown", 157 | "source": [ 158 | "#举例路径的生成与分解" 159 | ], 160 | "metadata": {} 161 | }, 162 | { 163 | "cell_type": "code", 164 | "source": [ 165 | "### 创建新文件夹。如果中间路径的文件夹不存在,那么就会把中间文件夹创建上\n", 166 | "os.makedirs('C:\\\\onedrive\\\\jupyter\\\\testmkdir\\\\1')\n", 167 | "#也可以使用mkdir创建,但是中间目录必须存在,否则报错\n", 168 | "os.mkdir('C:\\\\onedrive\\\\jupyter\\\\testmkdir2\\\\2')" 169 | ], 170 | "outputs": [], 171 | "execution_count": null, 172 | "metadata": { 173 | "collapsed": true 174 | } 175 | }, 176 | { 177 | "cell_type": "code", 178 | "source": [ 179 | "#举例路径的生成与分解\n", 180 | "p = Path('a','b','f/z')\n", 181 | "print(p)\n", 182 | "p2 = p / 'new_str'\n", 183 | "print(p2)\n", 184 | "p3 = '/new_str' / p\n", 185 | "print(p3)\n", 186 | "p4 = p3 / p\n", 187 | "print(p4)" 188 | ], 189 | "outputs": [ 190 | { 191 | "output_type": "stream", 192 | "name": "stdout", 193 | "text": [ 194 | "a\\b\\f\\z\n", 195 | "a\\b\\f\\z\\new_str\n", 196 | "\\new_str\\a\\b\\f\\z\n", 197 | "\\new_str\\a\\b\\f\\z\\a\\b\\f\\z\n" 198 | ] 199 | } 200 | ], 201 | "execution_count": 8, 202 | "metadata": {} 203 | }, 204 | { 205 | "cell_type": "code", 206 | "source": [ 207 | "p3.joinpath('etc','ab',Path('http')) # joinpath 拼接,等效于 p3.joinpath('etc','ab','http')" 208 | ], 209 | "outputs": [ 210 | { 211 | "output_type": "execute_result", 212 | "execution_count": 9, 213 | "data": { 214 | "text/plain": [ 215 | "WindowsPath('/new_str/a/b/f/z/etc/ab/http')" 216 | ] 217 | }, 218 | "metadata": {} 219 | } 220 | ], 221 | "execution_count": 9, 222 | "metadata": {} 223 | }, 224 | { 225 | "cell_type": "code", 226 | "source": [ 227 | "print(p4.parts)#路径分割: parts方法" 228 | ], 229 | "outputs": [ 230 | { 231 | "output_type": "stream", 232 | "name": "stdout", 233 | "text": [ 234 | "('\\\\', 'new_str', 'a', 'b', 'f', 'z', 'a', 'b', 'f', 'z')\n" 235 | ] 236 | } 237 | ], 238 | "execution_count": 10, 239 | "metadata": {} 240 | }, 241 | { 242 | "cell_type": "markdown", 243 | "source": [ 244 | "## 获取路径" 245 | ], 246 | "metadata": {} 247 | }, 248 | { 249 | "cell_type": "code", 250 | "source": [ 251 | "##路径的获取\n", 252 | "p4 = Path('/new_str/a/b/f/z/a/b/f/z')\n", 253 | "print(p4.parent)#获取目录\n", 254 | "print(p4.parents)#获取父目录\n", 255 | "\n", 256 | "for x in p4.parents:\n", 257 | " print(x)" 258 | ], 259 | "outputs": [ 260 | { 261 | "output_type": "stream", 262 | "name": "stdout", 263 | "text": [ 264 | "\\new_str\\a\\b\\f\\z\\a\\b\\f\n", 265 | "\n", 266 | "\\new_str\\a\\b\\f\\z\\a\\b\\f\n", 267 | "\\new_str\\a\\b\\f\\z\\a\\b\n", 268 | "\\new_str\\a\\b\\f\\z\\a\n", 269 | "\\new_str\\a\\b\\f\\z\n", 270 | "\\new_str\\a\\b\\f\n", 271 | "\\new_str\\a\\b\n", 272 | "\\new_str\\a\n", 273 | "\\new_str\n", 274 | "\\\n" 275 | ] 276 | } 277 | ], 278 | "execution_count": 14, 279 | "metadata": {} 280 | }, 281 | { 282 | "cell_type": "code", 283 | "source": [ 284 | "str(p)" 285 | ], 286 | "outputs": [ 287 | { 288 | "output_type": "execute_result", 289 | "execution_count": 13, 290 | "data": { 291 | "text/plain": [ 292 | "'\\\\etc'" 293 | ] 294 | }, 295 | "metadata": {} 296 | } 297 | ], 298 | "execution_count": 13, 299 | "metadata": {} 300 | }, 301 | { 302 | "cell_type": "code", 303 | "source": [ 304 | "p = Path('/etc')\n", 305 | "print(str(p),'\\n',bytes(p))" 306 | ], 307 | "outputs": [ 308 | { 309 | "output_type": "stream", 310 | "name": "stdout", 311 | "text": [ 312 | "\\etc \n", 313 | " b'\\\\etc'\n" 314 | ] 315 | } 316 | ], 317 | "execution_count": 11, 318 | "metadata": {} 319 | }, 320 | { 321 | "cell_type": "markdown", 322 | "source": [ 323 | "### 1.1.3 其它一些路径扩展操作" 324 | ], 325 | "metadata": {} 326 | }, 327 | { 328 | "cell_type": "code", 329 | "source": [ 330 | "p = Path('/a/b/c/d/g.tar.gz.a')\n", 331 | "\n", 332 | "print(p.name) #取basename\n", 333 | "print(p.suffix) #取目录最后一部分的扩展名,最后一个小数点部分。包括小数点。\n", 334 | "print(p.suffixes) #取从左到右第一个小数点右侧的部分,小数点分割。每部分都带小数点。\n", 335 | "print(p.stem) #取basename 排除最后一个小数点部分\n", 336 | "print(p.with_name('233.tgz')) #补仓后缀\n", 337 | "print(p.with_suffix('.txt')) #补后缀" 338 | ], 339 | "outputs": [ 340 | { 341 | "output_type": "stream", 342 | "name": "stdout", 343 | "text": [ 344 | "g.tar.gz.a\n", 345 | ".a\n", 346 | "['.tar', '.gz', '.a']\n", 347 | "g.tar.gz\n", 348 | "\\a\\b\\c\\d\\233.tgz\n", 349 | "\\a\\b\\c\\d\\g.tar.gz.txt\n" 350 | ] 351 | } 352 | ], 353 | "execution_count": 15, 354 | "metadata": {} 355 | }, 356 | { 357 | "cell_type": "code", 358 | "source": [ 359 | "p = Path('../tmp/')\n", 360 | "print(p.cwd()) #获取当前所在目录\n", 361 | "print(p.home()) #获取当前用户的家目录\n", 362 | "print(p.is_dir()) #判断是否为目录\n", 363 | "print(p.is_file())#判断是否为文件\n", 364 | "print(p.is_symlink()) #判断是否为软连接\n", 365 | "print(p.is_socket()) #判断是否为socket 文件\n", 366 | "print(p.is_block_device()) #判断是否为块设备\n", 367 | "print(p.is_char_device()) #判断是否为字符设备\n", 368 | "print(p.is_absolute()) #判断是否为绝对路径\n", 369 | "print(p.resolve()) #返回绝对路径,推荐使用\n", 370 | "print(p.absolute()) #返回绝对路径 \n", 371 | "print(p.exists()) #判断文件或者目录是否存在" 372 | ], 373 | "outputs": [ 374 | { 375 | "output_type": "stream", 376 | "name": "stdout", 377 | "text": [ 378 | "F:\\jupyter\\浩彬分享的代码\n", 379 | "C:\\Users\\x1c\n", 380 | "False\n", 381 | "False\n", 382 | "False\n", 383 | "False\n", 384 | "False\n", 385 | "False\n", 386 | "False\n", 387 | "F:\\jupyter\\tmp\n", 388 | "F:\\jupyter\\浩彬分享的代码\\..\\tmp\n", 389 | "False\n" 390 | ] 391 | } 392 | ], 393 | "execution_count": 16, 394 | "metadata": {} 395 | }, 396 | { 397 | "cell_type": "code", 398 | "source": [ 399 | "p5 = Path('/b/b/c')\n", 400 | "p5.as_uri() #返回文件的uri\n", 401 | "\n", 402 | "#说明:不能使用相对路径" 403 | ], 404 | "outputs": [], 405 | "execution_count": null, 406 | "metadata": { 407 | "collapsed": true 408 | } 409 | }, 410 | { 411 | "cell_type": "code", 412 | "source": [ 413 | "#设置路径变量\n", 414 | "p1 =Path('/jupyter/tmp/a/b')\n", 415 | "p2 =Path('/jupyter/tmp/a/b/3.txt')\n", 416 | "\n", 417 | "# 创建文件\n", 418 | "p1.mkdir(parents= True,exist_ok= True)\n", 419 | "p2.touch()\n", 420 | "\n", 421 | "# 检测文件是否创建成功\n", 422 | "print(p2.exists())\n", 423 | "\n", 424 | "#在a/b下创建新文件\n", 425 | "p1 /= 'readme.txt'\n", 426 | "p1.touch()\n", 427 | "print(p1)\n", 428 | "print(p1.exists())" 429 | ], 430 | "outputs": [ 431 | { 432 | "output_type": "stream", 433 | "name": "stdout", 434 | "text": [ 435 | "True\n", 436 | "\\jupyter\\tmp\\a\\b\\readme.txt\n", 437 | "True\n" 438 | ] 439 | } 440 | ], 441 | "execution_count": 17, 442 | "metadata": {} 443 | }, 444 | { 445 | "cell_type": "markdown", 446 | "source": [ 447 | "## 1.2 模块引用\n", 448 | "\n", 449 | "在Python中,模块就是一个有.py扩展名、包含Python代码的文件。一般分为import第三方库和自己创建的方法模块: \n", 450 | "### 1.2.1 引用第三方库" 451 | ], 452 | "metadata": {} 453 | }, 454 | { 455 | "cell_type": "code", 456 | "source": [ 457 | "# 直接导入Python的内置基础数学库,当要使用其中的某个变量可以使用math.cos\n", 458 | "import math\n", 459 | "print(math.cos(math.pi))\n", 460 | "\n", 461 | "# 可以起个别名,方便使用或避免名字冲突\n", 462 | "import math as m\n", 463 | "print(m.cos(m.pi))\n", 464 | "\n", 465 | "# 从math中导入cos函数和pi变量,可以直接使用cos\n", 466 | "from math import cos, pi\n", 467 | "print(cos(pi))" 468 | ], 469 | "outputs": [], 470 | "execution_count": null, 471 | "metadata": { 472 | "collapsed": true 473 | } 474 | }, 475 | { 476 | "cell_type": "code", 477 | "source": [], 478 | "outputs": [], 479 | "execution_count": null, 480 | "metadata": { 481 | "collapsed": true 482 | } 483 | }, 484 | { 485 | "cell_type": "markdown", 486 | "source": [ 487 | "### 1.2.2 引用创建的py文件\n", 488 | "#### 本文件为python基础,若调用同级目录,可以直接import \n", 489 | "目录结构如下\n", 490 | "- script \n", 491 | " - --python基础 \n", 492 | " - --myfun.py " 493 | ], 494 | "metadata": {} 495 | }, 496 | { 497 | "cell_type": "code", 498 | "source": [ 499 | "#可以直接使用\n", 500 | "import myfun\n", 501 | "#myfun.add(3,4)" 502 | ], 503 | "outputs": [], 504 | "execution_count": 19, 505 | "metadata": { 506 | "collapsed": true 507 | } 508 | }, 509 | { 510 | "cell_type": "markdown", 511 | "source": [ 512 | "#### 本文件为python基础,若调用子目录下的模块,需要增加from import \n", 513 | "目录结构如下\n", 514 | "- script \n", 515 | " - --python基础 \n", 516 | " - --myfun.py \n", 517 | " - --sub_fun \n", 518 | " - --sub_myfun.py" 519 | ], 520 | "metadata": {} 521 | }, 522 | { 523 | "cell_type": "code", 524 | "source": [ 525 | "from sub_fun import sub_myfun\n", 526 | "sub_myfun.sub_add(4,5)" 527 | ], 528 | "outputs": [], 529 | "execution_count": null, 530 | "metadata": { 531 | "collapsed": true 532 | } 533 | }, 534 | { 535 | "cell_type": "markdown", 536 | "source": [ 537 | "#### 本文件为python基础,若调用其他子目录下的模块,需要把所调用py文件对应上一级目录的路径添加到配置环境中,然后from import \n", 538 | "目录结构如下\n", 539 | "- upp_fun \n", 540 | " - --upp_myfun\n", 541 | "- script \n", 542 | " - --python基础 \n", 543 | " - --myfun.py \n", 544 | " - --sub_fun \n", 545 | " - --sub_myfun.py" 546 | ], 547 | "metadata": {} 548 | }, 549 | { 550 | "cell_type": "code", 551 | "source": [ 552 | "#指定路径\n", 553 | "import sys\n", 554 | "sys.path.append('C:\\\\onedrive\\\\jupyter')\n", 555 | "#应该也可以sys.path.append('..')\n", 556 | "from upp_fun import upp_myfun\n", 557 | "upp_myfun.upp_add(4,5)" 558 | ], 559 | "outputs": [], 560 | "execution_count": null, 561 | "metadata": { 562 | "collapsed": true 563 | } 564 | }, 565 | { 566 | "cell_type": "markdown", 567 | "source": [ 568 | "### __init__.py 文件说明\n", 569 | "\n", 570 | "在python模块的每一个包中,都有一个__init__.py文件(这个文件定义了包的属性和方法)然后是一些模块文件和子目录,假如子目录中也有__init__.py 那么它就是这个包的子包了。当你将一个包作为模块导入的时候,实际上导入了它的__init__.py 文件。\n", 571 | "\n", 572 | "一个包是一个带有特殊文件 __init__.py 的目录。__init__.py 文件定义了包的属性和方法。其实它可以什么也不定义;可以只是一个空文件,但是必须存在。如果 __init__.py 不存在,这个目录就仅仅是一个目录,而不是一个包,它就不能被导入或者包含其它的模块和嵌套包。\n", 573 | "\n", 574 | "__init__.py 中还有一个重要的变量,叫做__all__。\n", 575 | "当全部导入模块时(from 模块 import *),import 就会把注册在包__init__.py 文件中 __all__ 列表中的子模块和子包导入到当前作用域中来\n", 576 | "\n", 577 | "__init__.py的作用:\n", 578 | "\n", 579 | "package的标识,不能删除\n", 580 | "定义package中的__all__,用来模糊导入\n", 581 | "编写Python代码(不建议在__init__中写python模块,可以在包中在创建另外的模块来写,尽量保证__init__.py简单)" 582 | ], 583 | "metadata": {} 584 | }, 585 | { 586 | "cell_type": "markdown", 587 | "source": [ 588 | "# 2. python常用语法结构\n", 589 | "## 2.1 python运算符\n", 590 | "https://www.runoob.com/python/python-operators.html\n", 591 | "* 算术运算符\n", 592 | "* 比较(关系)运算符\n", 593 | "* 赋值运算符\n", 594 | "* 逻辑运算符\n", 595 | "* 位运算符\n" 596 | ], 597 | "metadata": {} 598 | }, 599 | { 600 | "cell_type": "code", 601 | "source": [ 602 | "a+b a加b\n", 603 | "a-b a减b\n", 604 | "a*b a乘以b\n", 605 | "a/b a除以b\n", 606 | "a//b a除以b,结果只取整数部分\n", 607 | "a**b a的b次幂\n", 608 | "a&b a或b都为True,则为True;对于整数,取逐位AND\n", 609 | "a|b a或b有一个为True,则为True;对于整数,取逐位OR\n", 610 | "a^b 对于布尔,a或b有一个为True,则为True,二者都为True,为False;对于整数,取逐位EXCLUSIVE-OR\n", 611 | "a==b a等于b,则为True\n", 612 | "a!=b a不等于b,则为True\n", 613 | "a=b a大于(或大于等于)b,则为True\n", 615 | "a is b a和b引用同一个Python对象,则为True\n", 616 | "a is not b a和b引用不同的Python对象,则为True" 617 | ], 618 | "outputs": [], 619 | "execution_count": null, 620 | "metadata": { 621 | "collapsed": true 622 | } 623 | }, 624 | { 625 | "cell_type": "code", 626 | "source": [ 627 | "#is比较与==运算符不同,s 检查的是两个对象是否相同,而不是相等\n", 628 | "a = b = [1,2,3]\n", 629 | "c = [1,2,3]\n", 630 | "a == b, a == c,a is b,a is c\n", 631 | "#变量 x 和 y 指向同一个列表,而c 指向另一个列表,虽然两个的值都是一样,但是并不是同一个对象,所以这里 a is c 返回 False" 632 | ], 633 | "outputs": [], 634 | "execution_count": null, 635 | "metadata": { 636 | "collapsed": true 637 | } 638 | }, 639 | { 640 | "cell_type": "markdown", 641 | "source": [ 642 | "## 2.2 控制流语句\n", 643 | "### 2.2.1 for循环\n", 644 | "for循环是在一个集合(列表或元组)中进行迭代,或者就是一个迭代器。" 645 | ], 646 | "metadata": {} 647 | }, 648 | { 649 | "cell_type": "code", 650 | "source": [ 651 | "#range可以接受三个参数,分别是起始值,上限(不包括上限),步长\n", 652 | "for i in range(10,19,2):\n", 653 | " print(i)\n", 654 | "\n", 655 | "#for循环在一行,[for]\n", 656 | "x= [1 for i in range(5)]\n", 657 | "x" 658 | ], 659 | "outputs": [ 660 | { 661 | "output_type": "stream", 662 | "name": "stdout", 663 | "text": [ 664 | "10\n", 665 | "12\n", 666 | "14\n", 667 | "16\n", 668 | "18\n" 669 | ] 670 | }, 671 | { 672 | "output_type": "execute_result", 673 | "execution_count": 21, 674 | "data": { 675 | "text/plain": [ 676 | "[1, 1, 1, 1, 1]" 677 | ] 678 | }, 679 | "metadata": {} 680 | } 681 | ], 682 | "execution_count": 21, 683 | "metadata": {} 684 | }, 685 | { 686 | "cell_type": "markdown", 687 | "source": [ 688 | "### 2.2.2 if、elif和else\n", 689 | "if是最广为人知的控制流语句。它检查一个条件,如果为True,就执行后面的语句。可以只使用if而不使用else\n", 690 | "可以使用if-elif-else的结构,中间可以包括多个elif。" 691 | ], 692 | "metadata": {} 693 | }, 694 | { 695 | "cell_type": "code", 696 | "source": [ 697 | "##猜数字游戏\n", 698 | "import random\n", 699 | "print('请猜一个1-20的数字,你有6次机会')\n", 700 | "answer = random.randint(1,20)\n", 701 | "for i in range(1,3):\n", 702 | " print('请输入:')\n", 703 | " num = int(input())\n", 704 | " if num > answer:\n", 705 | " print(\"太大了,再猜一个\")\n", 706 | " elif num < answer:\n", 707 | " print('太小了,再猜一个')\n", 708 | " else:\n", 709 | " break\n", 710 | "if num == answer:\n", 711 | " print('恭喜你猜中了!正确答案是%d' %answer )\n", 712 | "else:\n", 713 | " print('已经超过限制次数了,正确答案是%d' %answer)" 714 | ], 715 | "outputs": [ 716 | { 717 | "output_type": "stream", 718 | "name": "stdout", 719 | "text": [ 720 | "请猜一个1-20的数字,你有6次机会\n", 721 | "请输入:\n", 722 | "2\n", 723 | "太小了,再猜一个\n", 724 | "请输入:\n", 725 | "34\n", 726 | "太大了,再猜一个\n", 727 | "已经超过限制次数了,正确答案是5\n" 728 | ] 729 | } 730 | ], 731 | "execution_count": 1, 732 | "metadata": {} 733 | }, 734 | { 735 | "cell_type": "markdown", 736 | "source": [ 737 | "### 2.2.3While循环\n", 738 | "while循环指定了条件和代码,当条件为False或用break退出循环,代码才会退出" 739 | ], 740 | "metadata": {} 741 | }, 742 | { 743 | "cell_type": "code", 744 | "source": [ 745 | "##使用标志\n", 746 | "#导致程序结束的事件有很多时,如果在一条while 语句中检查所有这些条件,将既复杂又困难。\n", 747 | "#在要求很多条件都满足才继续运行的程序中,可定义一个变量\n", 748 | "#用于判断整个程序是否处于活动状态。这个变量被称为标志 \n", 749 | "prompt = \"\\nTell me something, and I will repeat it back to you:\"\n", 750 | "prompt += \"\\nEnter 'quit' to end the program. \"\n", 751 | "active = True\n", 752 | "while active:\n", 753 | " message = input(prompt)\n", 754 | " if message == 'quit':\n", 755 | " active = False\n", 756 | " else:\n", 757 | " print(message)" 758 | ], 759 | "outputs": [], 760 | "execution_count": null, 761 | "metadata": { 762 | "collapsed": true 763 | } 764 | }, 765 | { 766 | "cell_type": "markdown", 767 | "source": [ 768 | "### 2.2.3 pass、continue、break" 769 | ], 770 | "metadata": {} 771 | }, 772 | { 773 | "cell_type": "code", 774 | "source": [ 775 | "#pass是Python中的非操作语句。代码块不需要任何动作时可以使用(作为未执行代码的占位符);因为Python需要使用空白字符划定代码块,所以需要pass\n", 776 | "x=0\n", 777 | "if x < 0:\n", 778 | " print('negative!')\n", 779 | "elif x == 0:\n", 780 | " pass\n", 781 | "else:\n", 782 | " print('positive!')\n", 783 | "\n", 784 | "#continue,跳过该次循环;if+continue,符合条件的跳出循环\n", 785 | "#输出双数\n", 786 | "i = 0\n", 787 | "while i < 10:\n", 788 | " i=i+1\n", 789 | " if i%2 >0:\n", 790 | " continue\n", 791 | " print(i)\n", 792 | "\n", 793 | "#break,跳出整个循环\n", 794 | "i=1\n", 795 | "while 1:\n", 796 | " print(i)\n", 797 | " i = i+1\n", 798 | " if i >5:\n", 799 | " break" 800 | ], 801 | "outputs": [], 802 | "execution_count": null, 803 | "metadata": { 804 | "collapsed": true 805 | } 806 | }, 807 | { 808 | "cell_type": "markdown", 809 | "source": [ 810 | "### 2.2.4 try..except\n", 811 | "try:\n", 812 | "\n", 813 | " 代码1\n", 814 | " \n", 815 | "except:\n", 816 | "\n", 817 | " 代码2\n", 818 | " \n", 819 | "finally:\n", 820 | "\n", 821 | " 代码3\n", 822 | "\n", 823 | "代码1发生异常就执行代码2,无论正常与否都要执行代码3." 824 | ], 825 | "metadata": {} 826 | }, 827 | { 828 | "cell_type": "code", 829 | "source": [ 830 | "#try和except\n", 831 | "#raise:主动触发异常\n", 832 | "try:\n", 833 | " raise EOFError\n", 834 | " print('EOFError 错误!')\n", 835 | "except EOFError:\n", 836 | " print('EOFError异常。')\n", 837 | "\n", 838 | "#try和else\n", 839 | "list = [1, 2, 3, 4, 5, 6, 7, 8]\n", 840 | "try:\n", 841 | " list.append(100)\n", 842 | " print(list[8])\n", 843 | "except IndexError:\n", 844 | " print('数组越界')\n", 845 | "else:\n", 846 | " print(list)\n", 847 | "\n", 848 | "#try和finally\n", 849 | "list = [1, 2, 3, 4, 5, 6, 7, 8]\n", 850 | "try:\n", 851 | " list.append(100)\n", 852 | " print(list[10])\n", 853 | "except IndexError:\n", 854 | " print('数组越界')\n", 855 | "finally:\n", 856 | " print(list)\n", 857 | "\n", 858 | "#raise 抛出一个异常,一旦执行raise语句,后面的代码就不执行了,可以结合try 使用\n", 859 | "try:\n", 860 | " raise EOFError\n", 861 | " print('Hello World !') #不执行\n", 862 | "except EOFError:\n", 863 | " print('EOFError 错误') # 打印 EOFError错误" 864 | ], 865 | "outputs": [], 866 | "execution_count": null, 867 | "metadata": { 868 | "collapsed": true 869 | } 870 | }, 871 | { 872 | "cell_type": "code", 873 | "source": [ 874 | "try:\n", 875 | " raise EOFError\n", 876 | " print('EOFError 错误!') #不执行\n", 877 | "except EOFError:\n", 878 | " print('hello') " 879 | ], 880 | "outputs": [ 881 | { 882 | "output_type": "stream", 883 | "name": "stdout", 884 | "text": [ 885 | "hello\n" 886 | ] 887 | } 888 | ], 889 | "execution_count": 3, 890 | "metadata": {} 891 | }, 892 | { 893 | "cell_type": "code", 894 | "source": [ 895 | "##with...as with语句时用于对try except finally 的简化\n", 896 | "f=open('file_name','r')\n", 897 | "try:\n", 898 | " r=f.read()\n", 899 | "except:\n", 900 | " pass\n", 901 | "finally:\n", 902 | " f.close()\n", 903 | " \n", 904 | "等价于\n", 905 | "\n", 906 | "with open('file_name','r') as f:\n", 907 | " r=f.read()" 908 | ], 909 | "outputs": [], 910 | "execution_count": null, 911 | "metadata": { 912 | "collapsed": true 913 | } 914 | }, 915 | { 916 | "cell_type": "markdown", 917 | "source": [ 918 | "## 2.3 常用关键字" 919 | ], 920 | "metadata": {} 921 | }, 922 | { 923 | "cell_type": "code", 924 | "source": [ 925 | "help(\"keywords\")" 926 | ], 927 | "outputs": [ 928 | { 929 | "output_type": "stream", 930 | "name": "stdout", 931 | "text": [ 932 | "\n", 933 | "Here is a list of the Python keywords. Enter any keyword to get more help.\n", 934 | "\n", 935 | "False def if raise\n", 936 | "None del import return\n", 937 | "True elif in try\n", 938 | "and else is while\n", 939 | "as except lambda with\n", 940 | "assert finally nonlocal yield\n", 941 | "break for not \n", 942 | "class from or \n", 943 | "continue global pass \n", 944 | "\n" 945 | ] 946 | } 947 | ], 948 | "execution_count": 4, 949 | "metadata": {} 950 | }, 951 | { 952 | "cell_type": "markdown", 953 | "source": [ 954 | "### 2.3.1内置常量False、None、True" 955 | ], 956 | "metadata": {} 957 | }, 958 | { 959 | "cell_type": "code", 960 | "source": [ 961 | "#False == 0 ,True == 1,type(False),type(None) " 962 | ], 963 | "outputs": [], 964 | "execution_count": null, 965 | "metadata": { 966 | "collapsed": true 967 | } 968 | }, 969 | { 970 | "cell_type": "markdown", 971 | "source": [ 972 | "### 2.3.2 逻辑与 或 非 and or not¶\n", 973 | "优先级:not and or" 974 | ], 975 | "metadata": {} 976 | }, 977 | { 978 | "cell_type": "code", 979 | "source": [ 980 | "# x and y 如果 x 为 False 、空、0,返 回 x,否则返回 y\n", 981 | "# x or y 如果 x 为 False、 空、0,返回 y,否则返回x\n", 982 | "# not x 如果 x 为 False、 空、0,返回 True,否则返回False\n", 983 | "\n", 984 | "a = '1'\n", 985 | "b = 1\n", 986 | "a and b,a or y,not a" 987 | ], 988 | "outputs": [ 989 | { 990 | "output_type": "execute_result", 991 | "execution_count": 5, 992 | "data": { 993 | "text/plain": [ 994 | "(1, '1', False)" 995 | ] 996 | }, 997 | "metadata": {} 998 | } 999 | ], 1000 | "execution_count": 5, 1001 | "metadata": {} 1002 | }, 1003 | { 1004 | "cell_type": "markdown", 1005 | "source": [ 1006 | "### 2.3.2 用来定义的关键字def、class、lambda\n", 1007 | "* def : 定义一个函数或方法;\n", 1008 | "* class: 定义一个类对象;\n", 1009 | "* lambda:定义一个匿名函数;" 1010 | ], 1011 | "metadata": {} 1012 | }, 1013 | { 1014 | "cell_type": "code", 1015 | "source": [ 1016 | "class Student():\n", 1017 | " def __init__(self, name, age):\n", 1018 | " self.name = name\n", 1019 | " self.age = age\n", 1020 | "\n", 1021 | " def info(self):\n", 1022 | " print('name:', self.name)\n", 1023 | " print('age:', self.age)\n", 1024 | "\n", 1025 | "stu = Student('didi', 20)\n", 1026 | "stu.info()" 1027 | ], 1028 | "outputs": [], 1029 | "execution_count": null, 1030 | "metadata": { 1031 | "collapsed": true 1032 | } 1033 | }, 1034 | { 1035 | "cell_type": "code", 1036 | "source": [ 1037 | "def short_function(x):\n", 1038 | " return x * 2\n", 1039 | "\n", 1040 | "#等价于\n", 1041 | "equiv_anon = lambda x: x * 2\n", 1042 | "\n", 1043 | "def apply_to_list(some_list, f):\n", 1044 | " return [f(x) for x in some_list]\n", 1045 | "#虽然你可以直接编写[x *2for x in ints],但是这里我们可以非常轻松地传入一个自定义运算给apply_to_list函数。\n", 1046 | "ints = [4, 0, 1, 5, 6]\n", 1047 | "apply_to_list(ints, lambda x: x * 2)" 1048 | ], 1049 | "outputs": [ 1050 | { 1051 | "output_type": "execute_result", 1052 | "execution_count": 6, 1053 | "data": { 1054 | "text/plain": [ 1055 | "[8, 0, 2, 10, 12]" 1056 | ] 1057 | }, 1058 | "metadata": {} 1059 | } 1060 | ], 1061 | "execution_count": 6, 1062 | "metadata": {} 1063 | }, 1064 | { 1065 | "cell_type": "markdown", 1066 | "source": [ 1067 | "### 2.3.3 控制流关键字(参考以上语句部分)\n", 1068 | "if...elif...else...:条件判断;\n", 1069 | "\n", 1070 | "for...in...:对可迭代对象循环遍历\n", 1071 | "\n", 1072 | "for...in...else...:遍历正常完成则执行else后的代码;\n", 1073 | "\n", 1074 | "continue:终止本次循环,继续下一次循环;\n", 1075 | "\n", 1076 | "break:跳出循环;\n", 1077 | "\n", 1078 | "while:循环结构;\n", 1079 | "\n", 1080 | "return:函数返回值;" 1081 | ], 1082 | "metadata": {} 1083 | }, 1084 | { 1085 | "cell_type": "markdown", 1086 | "source": [ 1087 | "### 2.3.4 变量命令空间关键字\n", 1088 | "* global:将模块空间变量引入到局部空间修改;\n", 1089 | "* nonlocal:将本局部空间的外层空间变量引入到本层局部空间修改,用来嵌套函数内;" 1090 | ], 1091 | "metadata": {} 1092 | }, 1093 | { 1094 | "cell_type": "code", 1095 | "source": [ 1096 | "#定义全局变量:变量名全部大写\n", 1097 | "NAME = 'didi'\n", 1098 | "\n", 1099 | "#得到NAME\n", 1100 | "def get_NAME():\n", 1101 | " return NAME\n", 1102 | "\n", 1103 | "#重新设置NAME的值\n", 1104 | "def set_NAME(name_value):\n", 1105 | " global NAME\n", 1106 | " NAME = name_value\n", 1107 | "\n", 1108 | "print(get_NAME())\n", 1109 | "set_NAME('didididi')\n", 1110 | "print(get_NAME())" 1111 | ], 1112 | "outputs": [], 1113 | "execution_count": null, 1114 | "metadata": { 1115 | "collapsed": true 1116 | } 1117 | }, 1118 | { 1119 | "cell_type": "code", 1120 | "source": [ 1121 | "#关键字nonlocal的作用与关键字global类似,使用nonlocal关键字可以在一个嵌套的函数中修改嵌套作用域中的变量\n", 1122 | "def foo1():\n", 1123 | " num = 2\n", 1124 | " def foo2():\n", 1125 | " nonlocal num\n", 1126 | " num = 5\n", 1127 | " foo2()\n", 1128 | " print('num = ', num)\n", 1129 | "\n", 1130 | "foo1() # num = 5" 1131 | ], 1132 | "outputs": [], 1133 | "execution_count": null, 1134 | "metadata": { 1135 | "collapsed": true 1136 | } 1137 | }, 1138 | { 1139 | "cell_type": "markdown", 1140 | "source": [ 1141 | "### 2.3.5 del/yield" 1142 | ], 1143 | "metadata": {} 1144 | }, 1145 | { 1146 | "cell_type": "code", 1147 | "source": [ 1148 | "list = [1, 2, 3, 4, 5, 6, 7]\n", 1149 | "del list[1]\n", 1150 | "print(list)\n" 1151 | ], 1152 | "outputs": [ 1153 | { 1154 | "output_type": "stream", 1155 | "name": "stdout", 1156 | "text": [ 1157 | "[1, 3, 4, 5, 6, 7]\n" 1158 | ] 1159 | } 1160 | ], 1161 | "execution_count": 7, 1162 | "metadata": {} 1163 | }, 1164 | { 1165 | "cell_type": "raw", 1166 | "source": [ 1167 | "迭代器:所有你可以用在for...in...语句中的都是可迭代的:比如lists,strings,files...因为这些可迭代的对象你可以随意的读取所以非常方便易用,但是你必须把它们的值放到内存里,当它们有很多值时就会消耗太多的内存.\n", 1168 | "生成器:生成器也是迭代器的一种,但是你只能迭代它们一次.原因很简单,因为它们不是全部存在内存里,它们只在要调用的时候在内存里生成。\n", 1169 | "yield 是一个类似 return 的关键字,只是这个函数返回的是个生成器\n", 1170 | "当你调用这个函数的时候,函数内部的代码并不立马执行 ,这个函数只是返回一个生成器对象\n", 1171 | "当你使用for进行迭代的时候,函数中的代码才会执行" 1172 | ], 1173 | "metadata": {} 1174 | }, 1175 | { 1176 | "cell_type": "code", 1177 | "source": [ 1178 | "# #yield在函数中的功能类似于return,不同的是yield每次返回结果之后函数并没有退出,而是每次遇到yield关键字后返回相应结果,并保留函数当前的运行状态,等待下一次的调用。\n", 1179 | "# 如果一个函数需要多次循环执行一个动作,并且每次执行的结果都是需要的,这种场景很适合使用yield实现。\n", 1180 | "# 包含yield的函数成为一个生成器,生成器同时也是一个迭代器,支持通过next方法获取下一个值。\n", 1181 | "\n", 1182 | "def fun():\n", 1183 | " for i in range(20):\n", 1184 | " x=yield i\n", 1185 | " print('good',x)\n", 1186 | "a=fun()\n", 1187 | "a.__next__()\n", 1188 | "x=a.send(5)\n", 1189 | "#print(x)" 1190 | ], 1191 | "outputs": [ 1192 | { 1193 | "output_type": "stream", 1194 | "name": "stdout", 1195 | "text": [ 1196 | "good 5\n" 1197 | ] 1198 | } 1199 | ], 1200 | "execution_count": 9, 1201 | "metadata": {} 1202 | }, 1203 | { 1204 | "cell_type": "markdown", 1205 | "source": [ 1206 | "### 2.4 python输入及其格式化输出\n", 1207 | "\n", 1208 | "#### input输入\n", 1209 | "\n", 1210 | "在python2.7中式需要raw_input()" 1211 | ], 1212 | "metadata": {} 1213 | }, 1214 | { 1215 | "cell_type": "code", 1216 | "source": [ 1217 | "#input可以接受一个参数,作为提示信息,当然参数可以是一个变量,方便输入更长的内容\n", 1218 | "prompt = \"If you tell us who you are, we can personalize the messages you see.\"\n", 1219 | "prompt += \"\\nWhat is your first name? \"\n", 1220 | "name = input(prompt)\n", 1221 | "print(\"\\nHello, \" + name + \"!\")" 1222 | ], 1223 | "outputs": [ 1224 | { 1225 | "output_type": "stream", 1226 | "name": "stdout", 1227 | "text": [ 1228 | "If you tell us who you are, we can personalize the messages you see.\n", 1229 | "What is your first name? lyt\n", 1230 | "\n", 1231 | "Hello, lyt!\n" 1232 | ] 1233 | } 1234 | ], 1235 | "execution_count": 62, 1236 | "metadata": {} 1237 | }, 1238 | { 1239 | "cell_type": "code", 1240 | "source": [ 1241 | "#需要注意的是,接受的输入即使是数字也会被转化为字符串,所以要想获得数字输入,要加int()\n", 1242 | "height = input(\"How tall are you, in inches? \")\n", 1243 | "height = int(height)\n", 1244 | "if height >= 36:\n", 1245 | " print(\"\\nYou're tall enough to ride!\")\n", 1246 | "else:\n", 1247 | " print(\"\\nYou'll be able to ride when you're a little older.\")" 1248 | ], 1249 | "outputs": [ 1250 | { 1251 | "output_type": "stream", 1252 | "name": "stdout", 1253 | "text": [ 1254 | "How tall are you, in inches? 100\n", 1255 | "\n", 1256 | "You're tall enough to ride!\n" 1257 | ] 1258 | } 1259 | ], 1260 | "execution_count": 63, 1261 | "metadata": {} 1262 | }, 1263 | { 1264 | "cell_type": "markdown", 1265 | "source": [ 1266 | "#### 格式化输出" 1267 | ], 1268 | "metadata": {} 1269 | }, 1270 | { 1271 | "cell_type": "raw", 1272 | "source": [ 1273 | "字符串格式化时百分号后面有不同的格式符号,代表要转换的不同类型,具体的表示符号如下面所示。 \n", 1274 | "格式符号 表示类型\n", 1275 | " %s 字符串\n", 1276 | " %r 不管什么都打印出来(很多时候和%s类似,但是%r还会输出进一步的对象)\n", 1277 | " %d/%i 十进制整数\n", 1278 | " %u 十进制整数\n", 1279 | " %o 八进制整数\n", 1280 | " %x/%X 十六进制整数\n", 1281 | " %e/%E 科学计数\n", 1282 | " %f/%F 浮点数\n", 1283 | " %% 输出%" 1284 | ], 1285 | "metadata": {} 1286 | }, 1287 | { 1288 | "cell_type": "code", 1289 | "source": [ 1290 | "name = 'haobin'\n", 1291 | "zone = 'com'\n", 1292 | "print('www.%s.%s'%(name,zone))\n", 1293 | "#小数\n", 1294 | "mean = 0.17234\n", 1295 | "print('%.2f%%' % (mean * 100))" 1296 | ], 1297 | "outputs": [ 1298 | { 1299 | "output_type": "stream", 1300 | "name": "stdout", 1301 | "text": [ 1302 | "www.haobin.com\n", 1303 | "17.23%\n" 1304 | ] 1305 | } 1306 | ], 1307 | "execution_count": 13, 1308 | "metadata": {} 1309 | }, 1310 | { 1311 | "cell_type": "code", 1312 | "source": [ 1313 | "##一样\n", 1314 | "print(\"I am %s years old.\" % 22)\n", 1315 | "print(\"I am %r years old.\" % 22)\n", 1316 | "\n", 1317 | "## 不一样,%r把单引号也输出了\n", 1318 | "text = \"I am %d years old.\" % 22\n", 1319 | "print(\"I said:%s.\" % text)\n", 1320 | "print(\"I said:%r.\" % text)\n", 1321 | "\n", 1322 | "#不一样,%r把对象也输出了\n", 1323 | "import datetime\n", 1324 | "d =datetime.date.today()\n", 1325 | "print(\"%s\" % d)\n", 1326 | "print(\"%r\" % d)" 1327 | ], 1328 | "outputs": [ 1329 | { 1330 | "output_type": "stream", 1331 | "name": "stdout", 1332 | "text": [ 1333 | "I am 22 years old.\n", 1334 | "I am 22 years old.\n", 1335 | "I said:I am 22 years old..\n", 1336 | "I said:'I am 22 years old.'.\n", 1337 | "2019-09-02\n", 1338 | "datetime.date(2019, 9, 2)\n" 1339 | ] 1340 | } 1341 | ], 1342 | "execution_count": 14, 1343 | "metadata": {} 1344 | }, 1345 | { 1346 | "cell_type": "code", 1347 | "source": [ 1348 | "#print的其他使用\n", 1349 | "print('Hello')\n", 1350 | "print('Hello',end=' ')#修改不用换行符结尾\n", 1351 | "print('Cats','Dogs','mice')\n", 1352 | "print('Cats','Dogs','mice',sep=',')" 1353 | ], 1354 | "outputs": [ 1355 | { 1356 | "output_type": "stream", 1357 | "name": "stdout", 1358 | "text": [ 1359 | "Hello\n", 1360 | "Hello Cats Dogs mice\n", 1361 | "Cats,Dogs,mice\n" 1362 | ] 1363 | } 1364 | ], 1365 | "execution_count": 15, 1366 | "metadata": {} 1367 | }, 1368 | { 1369 | "cell_type": "code", 1370 | "source": [ 1371 | "#格式符号为数字时前面可以加为数和补缺位如:%[0][总位数][.][小数位数]来设定要转换的样式\n", 1372 | "fValue = 8.123\n", 1373 | "print('%06.2f'%fValue) # 保留宽度为6的2位小数浮点型" 1374 | ], 1375 | "outputs": [ 1376 | { 1377 | "output_type": "stream", 1378 | "name": "stdout", 1379 | "text": [ 1380 | "008.12\n" 1381 | ] 1382 | } 1383 | ], 1384 | "execution_count": 57, 1385 | "metadata": {} 1386 | }, 1387 | { 1388 | "cell_type": "markdown", 1389 | "source": [ 1390 | "#### format的使用\n", 1391 | "位置匹配\n", 1392 | "\n", 1393 | "① 不带参数,即{}\n", 1394 | "\n", 1395 | "② 带数字参数,可调换顺序,即{1}、{2}\n", 1396 | "\n", 1397 | "③ 带关键字,即{a}、{to}" 1398 | ], 1399 | "metadata": {} 1400 | }, 1401 | { 1402 | "cell_type": "code", 1403 | "source": [ 1404 | "# 不带参数\n", 1405 | "print('{} {}'.format('hello','world')) # 结果:hello world\n", 1406 | "# 带数字参数\n", 1407 | "print('{0} {1}'.format('hello','world')) # 结果:hello world\n", 1408 | "# 参数顺序倒乱\n", 1409 | "print('{0} {1} {0}'.format('hello','world')) # 结果:hello world hello\n", 1410 | "# 带关键字参数\n", 1411 | "print('{a} {tom} {a}'.format(tom='hello',a='world')) # 结果:world hello world" 1412 | ], 1413 | "outputs": [ 1414 | { 1415 | "output_type": "stream", 1416 | "name": "stdout", 1417 | "text": [ 1418 | "hello world\n", 1419 | "hello world\n", 1420 | "hello world hello\n", 1421 | "world hello world\n" 1422 | ] 1423 | } 1424 | ], 1425 | "execution_count": 60, 1426 | "metadata": {} 1427 | }, 1428 | { 1429 | "cell_type": "code", 1430 | "source": [ 1431 | "# 通过索引\n", 1432 | "coord = (3, 5)\n", 1433 | "print('X: {0[0]}; Y: {0[1]}'.format(coord)) # 结果:'X: 3; Y: 5'\n", 1434 | "# 通过key键参数\n", 1435 | "a = {'a': 'test_a', 'b': 'test_b'}\n", 1436 | "print('X: {0[a]}; Y: {0[b]}'.format(a)) # 结果:'X: test_a; Y: test_b'" 1437 | ], 1438 | "outputs": [ 1439 | { 1440 | "output_type": "stream", 1441 | "name": "stdout", 1442 | "text": [ 1443 | "X: 3; Y: 5\n", 1444 | "X: test_a; Y: test_b\n" 1445 | ] 1446 | } 1447 | ], 1448 | "execution_count": 61, 1449 | "metadata": {} 1450 | }, 1451 | { 1452 | "cell_type": "raw", 1453 | "source": [ 1454 | "我们还可以通过在格式化指示符后面添加一个冒号来进行精确格式化。" 1455 | ], 1456 | "metadata": {} 1457 | }, 1458 | { 1459 | "cell_type": "raw", 1460 | "source": [ 1461 | "格式转换\n", 1462 | "'b' - 二进制。将数字以2为基数进行输出。\n", 1463 | "'c' - 字符。在打印之前将整数转换成对应的Unicode字符串。\n", 1464 | "'d' - 十进制整数。将数字以10为基数进行输出。\n", 1465 | "'o' - 八进制。将数字以8为基数进行输出。\n", 1466 | "'x' - 十六进制。将数字以16为基数进行输出,9以上的位数用小写字母。\n", 1467 | "'e' - 幂符号。用科学计数法打印数字。用'e'表示幂。\n", 1468 | "'g' - 一般格式。将数值以fixed-point格式输出。当数值特别大的时候,用幂形式打印。\n", 1469 | "'n' - 数字。当值为整数时和'd'相同,值为浮点数时和'g'相同。不同的是它会根据区域设置插入数字分隔符。\n", 1470 | "'%' - 百分数。将数值乘以100然后以fixed-point('f')格式打印,值后面会有一个百分号。" 1471 | ], 1472 | "metadata": {} 1473 | }, 1474 | { 1475 | "cell_type": "code", 1476 | "source": [ 1477 | "print('{:b}'.format(3))\n", 1478 | "print('{:c}'.format(20)) \n", 1479 | "print('{:d}'.format(20)) \n", 1480 | "print('{:o}'.format(20))\n", 1481 | "print('{:x}'.format(20)) \n", 1482 | "print('{:e}'.format(20))\n", 1483 | "print('{:g}'.format(20.1)) \n", 1484 | "print('{:f}'.format(20)) \n", 1485 | "print('{:n}'.format(20))\n", 1486 | "print('{:%}'.format(20))" 1487 | ], 1488 | "outputs": [ 1489 | { 1490 | "output_type": "stream", 1491 | "name": "stdout", 1492 | "text": [ 1493 | "11\n", 1494 | "\u0014\n", 1495 | "20\n", 1496 | "24\n", 1497 | "14\n", 1498 | "2.000000e+01\n", 1499 | "20.1\n", 1500 | "20.000000\n", 1501 | "20\n", 1502 | "2000.000000%\n" 1503 | ] 1504 | } 1505 | ], 1506 | "execution_count": 59, 1507 | "metadata": {} 1508 | }, 1509 | { 1510 | "cell_type": "markdown", 1511 | "source": [ 1512 | "### 匿名(lambda)函数\n", 1513 | "Python支持一种被称为匿名的、或lambda函数。它仅由单条语句组成,该语句的结果就是返回值。它是通过lambda关键字定义的,这个关键字没有别的含义,仅仅是说“我们正在声明的是一个匿名函数”。lambda函数之所以会被称为匿名函数,与def声明的函数不同,原因之一就是这种函数对象本身是没有提供名称name属性。" 1514 | ], 1515 | "metadata": {} 1516 | }, 1517 | { 1518 | "cell_type": "code", 1519 | "source": [ 1520 | "def short_function(x):\n", 1521 | " return x * 2\n", 1522 | "\n", 1523 | "#等价\n", 1524 | "\n", 1525 | "equiv_anon = lambda x: x * 2" 1526 | ], 1527 | "outputs": [], 1528 | "execution_count": null, 1529 | "metadata": { 1530 | "collapsed": true 1531 | } 1532 | }, 1533 | { 1534 | "cell_type": "code", 1535 | "source": [ 1536 | "def apply_to_list(some_list, f):\n", 1537 | " return [f(x) for x in some_list]\n", 1538 | "#虽然你可以直接编写[x *2for x in ints],但是这里我们可以非常轻松地传入一个自定义运算给apply_to_list函数。\n", 1539 | "ints = [4, 0, 1, 5, 6]\n", 1540 | "apply_to_list(ints, lambda x: x * 2)" 1541 | ], 1542 | "outputs": [], 1543 | "execution_count": null, 1544 | "metadata": { 1545 | "collapsed": true 1546 | } 1547 | }, 1548 | { 1549 | "cell_type": "code", 1550 | "source": [ 1551 | "def add_numbers(x, y):\n", 1552 | " return x + y\n", 1553 | "add_five = lambda y: add_numbers(5, y)\n", 1554 | "#add_numbers的第二个参数称为“柯里化的”(curried)。这里没什么特别花哨的东西,因为我们其实就只是定义了一个可以调用现有函数的新函数而已。" 1555 | ], 1556 | "outputs": [], 1557 | "execution_count": null, 1558 | "metadata": { 1559 | "collapsed": true 1560 | } 1561 | }, 1562 | { 1563 | "cell_type": "markdown", 1564 | "source": [ 1565 | "# 四、数据结构和序列" 1566 | ], 1567 | "metadata": {} 1568 | }, 1569 | { 1570 | "cell_type": "markdown", 1571 | "source": [ 1572 | "## 4.1 元组\n", 1573 | "元组是一个固定长度,不可改变的Python序列对象。创建元组的最简单方式,是用逗号分隔一列值" 1574 | ], 1575 | "metadata": {} 1576 | }, 1577 | { 1578 | "cell_type": "code", 1579 | "source": [ 1580 | "tu=(1)\n", 1581 | "tu2=(1,)\n", 1582 | "tu3=(1,2,3,4)\n", 1583 | "tu4=1,2,3,4\n", 1584 | "type(tu4)" 1585 | ], 1586 | "outputs": [ 1587 | { 1588 | "output_type": "execute_result", 1589 | "execution_count": 77, 1590 | "data": { 1591 | "text/plain": [ 1592 | "tuple" 1593 | ] 1594 | }, 1595 | "metadata": {} 1596 | } 1597 | ], 1598 | "execution_count": 77, 1599 | "metadata": {} 1600 | }, 1601 | { 1602 | "cell_type": "code", 1603 | "source": [ 1604 | "#用tuple可以将任意序列或迭代器转换成元组\n", 1605 | "tup = tuple('string')\n", 1606 | "tup" 1607 | ], 1608 | "outputs": [ 1609 | { 1610 | "output_type": "execute_result", 1611 | "execution_count": 78, 1612 | "data": { 1613 | "text/plain": [ 1614 | "('s', 't', 'r', 'i', 'n', 'g')" 1615 | ] 1616 | }, 1617 | "metadata": {} 1618 | } 1619 | ], 1620 | "execution_count": 78, 1621 | "metadata": {} 1622 | }, 1623 | { 1624 | "cell_type": "code", 1625 | "source": [ 1626 | "#元组是不可变的对象,但如果元组中的某个对象是可变的,比如列表,可以进行修改\n", 1627 | "tup = tuple(['foo', [1, 2], True])\n", 1628 | "tup[1].append(3)\n", 1629 | "tup" 1630 | ], 1631 | "outputs": [ 1632 | { 1633 | "output_type": "execute_result", 1634 | "execution_count": 79, 1635 | "data": { 1636 | "text/plain": [ 1637 | "('foo', [1, 2, 3], True)" 1638 | ] 1639 | }, 1640 | "metadata": {} 1641 | } 1642 | ], 1643 | "execution_count": 79, 1644 | "metadata": {} 1645 | }, 1646 | { 1647 | "cell_type": "code", 1648 | "source": [ 1649 | "#可以用加法和乘法串联\n", 1650 | "tup1 = (4, None, 'foo') + (6, 0) + ('bar',)\n", 1651 | "tup2 = ('foo', 'bar') * 5\n", 1652 | "tup1,tup2" 1653 | ], 1654 | "outputs": [ 1655 | { 1656 | "output_type": "execute_result", 1657 | "execution_count": 82, 1658 | "data": { 1659 | "text/plain": [ 1660 | "((4, None, 'foo', 6, 0, 'bar'),\n", 1661 | " ('foo', 'bar', 'foo', 'bar', 'foo', 'bar', 'foo', 'bar', 'foo', 'bar'))" 1662 | ] 1663 | }, 1664 | "metadata": {} 1665 | } 1666 | ], 1667 | "execution_count": 82, 1668 | "metadata": {} 1669 | }, 1670 | { 1671 | "cell_type": "code", 1672 | "source": [ 1673 | "#如果你想将元组赋值给类似元组的变量,Python会试图拆分等号右边的值\n", 1674 | "tup = (4, 5, 6)\n", 1675 | "a, b, c = tup\n", 1676 | "a,b,c" 1677 | ], 1678 | "outputs": [ 1679 | { 1680 | "output_type": "execute_result", 1681 | "execution_count": 85, 1682 | "data": { 1683 | "text/plain": [ 1684 | "(4, 5, 6)" 1685 | ] 1686 | }, 1687 | "metadata": {} 1688 | } 1689 | ], 1690 | "execution_count": 85, 1691 | "metadata": {} 1692 | }, 1693 | { 1694 | "cell_type": "code", 1695 | "source": [ 1696 | "#简单的元组替换\n", 1697 | "a , b = 1, 2\n", 1698 | "b , a = a,b\n", 1699 | "a,b" 1700 | ], 1701 | "outputs": [ 1702 | { 1703 | "output_type": "execute_result", 1704 | "execution_count": 86, 1705 | "data": { 1706 | "text/plain": [ 1707 | "(2, 1)" 1708 | ] 1709 | }, 1710 | "metadata": {} 1711 | } 1712 | ], 1713 | "execution_count": 86, 1714 | "metadata": {} 1715 | }, 1716 | { 1717 | "cell_type": "code", 1718 | "source": [ 1719 | "#Python最近新增了更多高级的元组拆分功能,允许从元组的开头“摘取”几个元素。\n", 1720 | "#它使用了特殊的语法*rest,这也用在函数签名中以抓取任意长度列表的位置参数\n", 1721 | "values = 1, 2, 3, 4, 5\n", 1722 | "a,b,*rest = values\n", 1723 | "a,b,rest\n", 1724 | "#rest的部分是想要舍弃的部分,rest的名字不重要。作为惯用写法,许多Python程序员会将不需要的变量使用下划线,即*_" 1725 | ], 1726 | "outputs": [ 1727 | { 1728 | "output_type": "execute_result", 1729 | "execution_count": 89, 1730 | "data": { 1731 | "text/plain": [ 1732 | "(1, 2, [3, 4, 5])" 1733 | ] 1734 | }, 1735 | "metadata": {} 1736 | } 1737 | ], 1738 | "execution_count": 89, 1739 | "metadata": {} 1740 | }, 1741 | { 1742 | "cell_type": "code", 1743 | "source": [ 1744 | "#count(也适用于列表),它可以统计某个值得出现频率\n", 1745 | "a = (1, 2, 2, 2, 3, 4, 2)\n", 1746 | "a.count(2)" 1747 | ], 1748 | "outputs": [ 1749 | { 1750 | "output_type": "execute_result", 1751 | "execution_count": 90, 1752 | "data": { 1753 | "text/plain": [ 1754 | "4" 1755 | ] 1756 | }, 1757 | "metadata": {} 1758 | } 1759 | ], 1760 | "execution_count": 90, 1761 | "metadata": {} 1762 | }, 1763 | { 1764 | "cell_type": "markdown", 1765 | "source": [ 1766 | "## 4.2 列表\n", 1767 | "与元组对比,列表的长度可变、内容可以被修改。列表属于可变的数据类型,因此可以添执行加、删除,或者是搜索列表中的项目。列表可以嵌套" 1768 | ], 1769 | "metadata": {} 1770 | }, 1771 | { 1772 | "cell_type": "code", 1773 | "source": [ 1774 | "li = [1,2,3,4]\n", 1775 | "li2 = ['a','b','c','d']\n", 1776 | "li3 = [1,2,'a','b']\n", 1777 | "li,li2,li3" 1778 | ], 1779 | "outputs": [ 1780 | { 1781 | "output_type": "execute_result", 1782 | "execution_count": 108, 1783 | "data": { 1784 | "text/plain": [ 1785 | "([1, 2, 3, 4], ['a', 'b', 'c', 'd'], [1, 2, 'a', 'b'])" 1786 | ] 1787 | }, 1788 | "metadata": {} 1789 | } 1790 | ], 1791 | "execution_count": 108, 1792 | "metadata": {} 1793 | }, 1794 | { 1795 | "cell_type": "code", 1796 | "source": [ 1797 | "a_list = [2, 3, 7, None]\n", 1798 | "a_list.append('dwarf')#append在列表末尾添加元素\n", 1799 | "a_list.insert(1, 'red')#insert可以在特定的位置插入元素\n", 1800 | "a_list" 1801 | ], 1802 | "outputs": [ 1803 | { 1804 | "output_type": "execute_result", 1805 | "execution_count": 115, 1806 | "data": { 1807 | "text/plain": [ 1808 | "[2, 'red', 3, 7, None, 'dwarf']" 1809 | ] 1810 | }, 1811 | "metadata": {} 1812 | } 1813 | ], 1814 | "execution_count": 115, 1815 | "metadata": {} 1816 | }, 1817 | { 1818 | "cell_type": "code", 1819 | "source": [ 1820 | "a_list.pop(2)#pop移除并返回指定位置的元素" 1821 | ], 1822 | "outputs": [ 1823 | { 1824 | "output_type": "execute_result", 1825 | "execution_count": 111, 1826 | "data": { 1827 | "text/plain": [ 1828 | "3" 1829 | ] 1830 | }, 1831 | "metadata": {} 1832 | } 1833 | ], 1834 | "execution_count": 111, 1835 | "metadata": {} 1836 | }, 1837 | { 1838 | "cell_type": "code", 1839 | "source": [ 1840 | "a_list.append('red')#再末尾加上'red'。这样就有两个'red'值\n", 1841 | "a_list.remove('red')#remove会先寻找第一个值并除去\n", 1842 | "a_list" 1843 | ], 1844 | "outputs": [ 1845 | { 1846 | "output_type": "execute_result", 1847 | "execution_count": 118, 1848 | "data": { 1849 | "text/plain": [ 1850 | "[2, 3, 7, None, 'dwarf', 'red']" 1851 | ] 1852 | }, 1853 | "metadata": {} 1854 | } 1855 | ], 1856 | "execution_count": 118, 1857 | "metadata": {} 1858 | }, 1859 | { 1860 | "cell_type": "code", 1861 | "source": [ 1862 | "#extend方法可以追加多个元素\n", 1863 | "x = [4, None, 'foo']\n", 1864 | "x.extend([7, 8, (2, 3)])\n", 1865 | "x" 1866 | ], 1867 | "outputs": [ 1868 | { 1869 | "output_type": "execute_result", 1870 | "execution_count": 119, 1871 | "data": { 1872 | "text/plain": [ 1873 | "[4, None, 'foo', 7, 8, (2, 3)]" 1874 | ] 1875 | }, 1876 | "metadata": {} 1877 | } 1878 | ], 1879 | "execution_count": 119, 1880 | "metadata": {} 1881 | }, 1882 | { 1883 | "cell_type": "code", 1884 | "source": [ 1885 | "#切片可以选取大多数序列类型的一部分,切片的基本形式是在方括号中使用。\n", 1886 | "#切片的起始元素是包括的,不包含结束元素。\n", 1887 | "seq = [7, 2, 3, 7, 5, 6, 0, 1]\n", 1888 | "seq[1:5],seq[:5]#start或stop都可以被省略,省略之后,分别默认序列的开头和结尾" 1889 | ], 1890 | "outputs": [ 1891 | { 1892 | "output_type": "execute_result", 1893 | "execution_count": 121, 1894 | "data": { 1895 | "text/plain": [ 1896 | "([2, 3, 7, 5], [7, 2, 3, 7, 5])" 1897 | ] 1898 | }, 1899 | "metadata": {} 1900 | } 1901 | ], 1902 | "execution_count": 121, 1903 | "metadata": {} 1904 | }, 1905 | { 1906 | "cell_type": "code", 1907 | "source": [ 1908 | "#遍历\n", 1909 | "lists = [\"m1\", 1900, \"m2\", 2000]\n", 1910 | "#1.使用iter()\n", 1911 | "for val in iter(lists):\n", 1912 | " print(val)\n", 1913 | "#2.enumerate遍历方法\n", 1914 | "for i, val in enumerate(lists):\n", 1915 | " print(i, val)\n", 1916 | "#3.索引遍历\n", 1917 | "for index in range(len(lists)):\n", 1918 | " print(lists[index])" 1919 | ], 1920 | "outputs": [ 1921 | { 1922 | "output_type": "stream", 1923 | "name": "stdout", 1924 | "text": [ 1925 | "m1\n", 1926 | "1900\n", 1927 | "m2\n", 1928 | "2000\n", 1929 | "0 m1\n", 1930 | "1 1900\n", 1931 | "2 m2\n", 1932 | "3 2000\n" 1933 | ] 1934 | } 1935 | ], 1936 | "execution_count": 77, 1937 | "metadata": {} 1938 | }, 1939 | { 1940 | "cell_type": "markdown", 1941 | "source": [ 1942 | "## 4.3 字典\n", 1943 | "字典可能是Python最为重要的数据结构。它更为常见的名字是哈希映射或关联数组。它是键值对的大小可变集合,键和值都是Python对象。字典使用花括号{}包括,键和值之间用冒号:分割,每对键-值”用逗号,分割 键必须唯一,即一个键不能对应多个值,不过多个键可以指向一个值。" 1944 | ], 1945 | "metadata": {} 1946 | }, 1947 | { 1948 | "cell_type": "code", 1949 | "source": [ 1950 | "#创建字典的方法之一是使用尖括号,用冒号分隔键和值:\n", 1951 | "empty_dict = {}\n", 1952 | "d1 = {'a' : 'some value', 'b' : [1, 2, 3, 4]}\n", 1953 | "d1" 1954 | ], 1955 | "outputs": [ 1956 | { 1957 | "output_type": "execute_result", 1958 | "execution_count": 5, 1959 | "data": { 1960 | "text/plain": [ 1961 | "{'a': 'some value', 'b': [1, 2, 3, 4]}" 1962 | ] 1963 | }, 1964 | "metadata": {} 1965 | } 1966 | ], 1967 | "execution_count": 5, 1968 | "metadata": {} 1969 | }, 1970 | { 1971 | "cell_type": "code", 1972 | "source": [ 1973 | "d1[7] = 'an integer'#插入字典中的元素,7为key,'an integer'为value\n", 1974 | "d1" 1975 | ], 1976 | "outputs": [ 1977 | { 1978 | "output_type": "execute_result", 1979 | "execution_count": 6, 1980 | "data": { 1981 | "text/plain": [ 1982 | "{7: 'an integer', 'a': 'some value', 'b': [1, 2, 3, 4]}" 1983 | ] 1984 | }, 1985 | "metadata": {} 1986 | } 1987 | ], 1988 | "execution_count": 6, 1989 | "metadata": {} 1990 | }, 1991 | { 1992 | "cell_type": "code", 1993 | "source": [ 1994 | "#del关键字或pop方法(返回值的同时删除键)删除值\n", 1995 | "d1[5] = 'some value'\n", 1996 | "print(d1)\n", 1997 | "d1['dummy'] = 'another value'\n", 1998 | "print(d1)\n", 1999 | "del d1[5]\n", 2000 | "print(d1)" 2001 | ], 2002 | "outputs": [ 2003 | { 2004 | "output_type": "stream", 2005 | "name": "stdout", 2006 | "text": [ 2007 | "{'a': 'some value', 'b': [1, 2, 3, 4], 7: 'an integer', 5: 'some value'}\n", 2008 | "{'a': 'some value', 'b': [1, 2, 3, 4], 7: 'an integer', 5: 'some value', 'dummy': 'another value'}\n", 2009 | "{'a': 'some value', 'b': [1, 2, 3, 4], 7: 'an integer', 'dummy': 'another value'}\n" 2010 | ] 2011 | } 2012 | ], 2013 | "execution_count": 7, 2014 | "metadata": {} 2015 | }, 2016 | { 2017 | "cell_type": "code", 2018 | "source": [ 2019 | "ret = d1.pop('dummy')\n", 2020 | "ret,d1" 2021 | ], 2022 | "outputs": [ 2023 | { 2024 | "output_type": "execute_result", 2025 | "execution_count": 8, 2026 | "data": { 2027 | "text/plain": [ 2028 | "('another value', {7: 'an integer', 'a': 'some value', 'b': [1, 2, 3, 4]})" 2029 | ] 2030 | }, 2031 | "metadata": {} 2032 | } 2033 | ], 2034 | "execution_count": 8, 2035 | "metadata": {} 2036 | }, 2037 | { 2038 | "cell_type": "code", 2039 | "source": [ 2040 | "#keys和values是字典的键和值的迭代器方法。虽然键值对没有顺序,这两个方法可以用相同的顺序输出键和值\n", 2041 | "list(d1.keys()),list(d1.values())" 2042 | ], 2043 | "outputs": [ 2044 | { 2045 | "output_type": "execute_result", 2046 | "execution_count": 9, 2047 | "data": { 2048 | "text/plain": [ 2049 | "(['a', 'b', 7], ['some value', [1, 2, 3, 4], 'an integer'])" 2050 | ] 2051 | }, 2052 | "metadata": {} 2053 | } 2054 | ], 2055 | "execution_count": 9, 2056 | "metadata": {} 2057 | }, 2058 | { 2059 | "cell_type": "code", 2060 | "source": [ 2061 | "#keys()返回键,values()返回值和items()方法返回键值对\n", 2062 | "#返回结果并不是真正的列表,因此不能被append和修改,但可以使用for循环或者强制转换\n", 2063 | "#字典转为列表\n", 2064 | "spam = {'color':'red','age':42}\n", 2065 | "spam.values()\n", 2066 | "for i in spam.items():\n", 2067 | " print(i)\n", 2068 | "#把返回结果换为列表\n", 2069 | "list(spam.keys())" 2070 | ], 2071 | "outputs": [ 2072 | { 2073 | "output_type": "stream", 2074 | "name": "stdout", 2075 | "text": [ 2076 | "('color', 'red')\n", 2077 | "('age', 42)\n" 2078 | ] 2079 | }, 2080 | { 2081 | "output_type": "execute_result", 2082 | "execution_count": 12, 2083 | "data": { 2084 | "text/plain": [ 2085 | "['color', 'age']" 2086 | ] 2087 | }, 2088 | "metadata": {} 2089 | } 2090 | ], 2091 | "execution_count": 12, 2092 | "metadata": {} 2093 | }, 2094 | { 2095 | "cell_type": "code", 2096 | "source": [ 2097 | "#字典的遍历\n", 2098 | "#1.遍历key值 在使用上,for key in a和 for key in a.keys():完全等价。\n", 2099 | "a={'a': '1', 'b': '2', 'c': '3'}\n", 2100 | "print(\"遍历key值:\")\n", 2101 | "for key in a:\n", 2102 | " print(key+':'+a[key])\n", 2103 | "#2.遍历value值\n", 2104 | "print(\"遍历value值:\")\n", 2105 | "for value in a.values():\n", 2106 | " print(value)\n", 2107 | "#3.遍历字典项\n", 2108 | "print(\"遍历字典项:\")\n", 2109 | "for kv in a.items():\n", 2110 | " print(kv)\n", 2111 | "#4.遍历字典健值\n", 2112 | "print(\"遍历字典健值:\")\n", 2113 | "for key,value in a.items():\n", 2114 | " print(key+':'+value)" 2115 | ], 2116 | "outputs": [ 2117 | { 2118 | "output_type": "stream", 2119 | "name": "stdout", 2120 | "text": [ 2121 | "遍历key值:\n", 2122 | "a:1\n", 2123 | "b:2\n", 2124 | "c:3\n", 2125 | "遍历value值:\n", 2126 | "1\n", 2127 | "2\n", 2128 | "3\n", 2129 | "遍历字典项:\n", 2130 | "('a', '1')\n", 2131 | "('b', '2')\n", 2132 | "('c', '3')\n", 2133 | "遍历字典健值:\n", 2134 | "a:1\n", 2135 | "b:2\n", 2136 | "c:3\n" 2137 | ] 2138 | } 2139 | ], 2140 | "execution_count": 76, 2141 | "metadata": {} 2142 | }, 2143 | { 2144 | "cell_type": "code", 2145 | "source": [ 2146 | "#update方法可以将一个字典与另一个融合\n", 2147 | "d1.update({'b' : 'foo', 'c' : 12})\n", 2148 | "d1" 2149 | ], 2150 | "outputs": [ 2151 | { 2152 | "output_type": "execute_result", 2153 | "execution_count": 10, 2154 | "data": { 2155 | "text/plain": [ 2156 | "{7: 'an integer', 'a': 'some value', 'b': 'foo', 'c': 12}" 2157 | ] 2158 | }, 2159 | "metadata": {} 2160 | } 2161 | ], 2162 | "execution_count": 10, 2163 | "metadata": {} 2164 | }, 2165 | { 2166 | "cell_type": "code", 2167 | "source": [ 2168 | "#字典总是明确地记录键和值之间的关联关系,但获取字典的元素时,获取顺序是不可预测的。\n", 2169 | "#要以特定的顺序返回元素,一种办法是在for 循环中对返回的键进行排序。\n", 2170 | "favorite_languages = {\n", 2171 | " 'jen': 'python',\n", 2172 | " 'sarah': 'c',\n", 2173 | " 'edward': 'ruby',\n", 2174 | " 'phil': 'python',\n", 2175 | "}\n", 2176 | "for name in sorted(favorite_languages.keys()):\n", 2177 | " print(name.title() + \", thank you for taking the poll.\")" 2178 | ], 2179 | "outputs": [ 2180 | { 2181 | "output_type": "stream", 2182 | "name": "stdout", 2183 | "text": [ 2184 | "Edward, thank you for taking the poll.\n", 2185 | "Jen, thank you for taking the poll.\n", 2186 | "Phil, thank you for taking the poll.\n", 2187 | "Sarah, thank you for taking the poll.\n" 2188 | ] 2189 | } 2190 | ], 2191 | "execution_count": 13, 2192 | "metadata": {} 2193 | }, 2194 | { 2195 | "cell_type": "code", 2196 | "source": [ 2197 | "#setdefault方法,比defaultdict方便,为字典中某个键设置一个默认值,当该键没有任何值时使用它。\n", 2198 | "#空字典可以直接增加变量,但是如果在Python中如果访问字典中不存在的键,会引发KeyError异常。\n", 2199 | "#由于键值是空的,所以不能直接访问\n", 2200 | "words = ['apple', 'bat', 'bar', 'atom', 'book']\n", 2201 | "by_letter = {}\n", 2202 | "for word in words:\n", 2203 | " letter = word[0]\n", 2204 | " by_letter.setdefault(letter, []).append(word)\n", 2205 | "by_letter" 2206 | ], 2207 | "outputs": [ 2208 | { 2209 | "output_type": "execute_result", 2210 | "execution_count": 15, 2211 | "data": { 2212 | "text/plain": [ 2213 | "{'a': ['apple', 'atom'], 'b': ['bat', 'bar', 'book']}" 2214 | ] 2215 | }, 2216 | "metadata": {} 2217 | } 2218 | ], 2219 | "execution_count": 15, 2220 | "metadata": {} 2221 | }, 2222 | { 2223 | "cell_type": "code", 2224 | "source": [ 2225 | "#collections模块有一个很有用的类,defaultdict,它可以进一步简化上面。传递类型或函数以生成每个位置的默认值\n", 2226 | "##defaultdict就是一个本身带有默认值的dict\n", 2227 | "#defaultdict类的初始化函数受一个类型作为参数,当接所访问的键不存在的时候,可以实例化一个值作为默认值\n", 2228 | "from collections import defaultdict\n", 2229 | "by_letter = defaultdict(list)\n", 2230 | "for word in words:\n", 2231 | " by_letter[word[0]].append(word)" 2232 | ], 2233 | "outputs": [], 2234 | "execution_count": null, 2235 | "metadata": { 2236 | "collapsed": true 2237 | } 2238 | }, 2239 | { 2240 | "cell_type": "code", 2241 | "source": [ 2242 | "# 字典转成dataframe\n", 2243 | "#1.直接使用pd.DataFrame()。\n", 2244 | "dict = {'a':'apple','b':'banana'}\n", 2245 | "import pandas as pd\n", 2246 | "df = pd.DataFrame([dict])\n", 2247 | "df" 2248 | ], 2249 | "outputs": [ 2250 | { 2251 | "output_type": "execute_result", 2252 | "execution_count": 66, 2253 | "data": { 2254 | "text/html": [ 2255 | "
\n", 2256 | "\n", 2269 | "\n", 2270 | " \n", 2271 | " \n", 2272 | " \n", 2273 | " \n", 2274 | " \n", 2275 | " \n", 2276 | " \n", 2277 | " \n", 2278 | " \n", 2279 | " \n", 2280 | " \n", 2281 | " \n", 2282 | " \n", 2283 | " \n", 2284 | "
ab
0applebanana
\n", 2285 | "
" 2286 | ], 2287 | "text/plain": [ 2288 | " a b\n", 2289 | "0 apple banana" 2290 | ] 2291 | }, 2292 | "metadata": {} 2293 | } 2294 | ], 2295 | "execution_count": 66, 2296 | "metadata": {} 2297 | }, 2298 | { 2299 | "cell_type": "code", 2300 | "source": [ 2301 | "#2.使用DataFrame的from_dict()方法。\n", 2302 | "df = pd.DataFrame.from_dict(dict,orient='index')\n", 2303 | "df = df.reset_index().rename(columns = {'index':'id'})\n", 2304 | "df" 2305 | ], 2306 | "outputs": [ 2307 | { 2308 | "output_type": "execute_result", 2309 | "execution_count": 48, 2310 | "data": { 2311 | "text/html": [ 2312 | "
\n", 2313 | "\n", 2326 | "\n", 2327 | " \n", 2328 | " \n", 2329 | " \n", 2330 | " \n", 2331 | " \n", 2332 | " \n", 2333 | " \n", 2334 | " \n", 2335 | " \n", 2336 | " \n", 2337 | " \n", 2338 | " \n", 2339 | " \n", 2340 | " \n", 2341 | " \n", 2342 | " \n", 2343 | " \n", 2344 | " \n", 2345 | " \n", 2346 | "
id0
0aapple
1bbanana
\n", 2347 | "
" 2348 | ], 2349 | "text/plain": [ 2350 | " id 0\n", 2351 | "0 a apple\n", 2352 | "1 b banana" 2353 | ] 2354 | }, 2355 | "metadata": {} 2356 | } 2357 | ], 2358 | "execution_count": 48, 2359 | "metadata": {} 2360 | }, 2361 | { 2362 | "cell_type": "code", 2363 | "source": [ 2364 | "#3.将字典转变为Series,再转为DataFrame。\n", 2365 | "df = pd.DataFrame(pd.Series(dict), columns=['fruits'])\n", 2366 | "df = df.reset_index().rename(columns={'index':'id'})\n", 2367 | "df" 2368 | ], 2369 | "outputs": [ 2370 | { 2371 | "output_type": "execute_result", 2372 | "execution_count": 41, 2373 | "data": { 2374 | "text/html": [ 2375 | "
\n", 2376 | "\n", 2389 | "\n", 2390 | " \n", 2391 | " \n", 2392 | " \n", 2393 | " \n", 2394 | " \n", 2395 | " \n", 2396 | " \n", 2397 | " \n", 2398 | " \n", 2399 | " \n", 2400 | " \n", 2401 | " \n", 2402 | " \n", 2403 | " \n", 2404 | " \n", 2405 | " \n", 2406 | " \n", 2407 | " \n", 2408 | " \n", 2409 | "
idfruits
0aapple
1bbanana
\n", 2410 | "
" 2411 | ], 2412 | "text/plain": [ 2413 | " id fruits\n", 2414 | "0 a apple\n", 2415 | "1 b banana" 2416 | ] 2417 | }, 2418 | "metadata": {} 2419 | } 2420 | ], 2421 | "execution_count": 41, 2422 | "metadata": {} 2423 | }, 2424 | { 2425 | "cell_type": "code", 2426 | "source": [ 2427 | "#4.reset_index().rename()方法,将作为index的keys变为DataFrame中的一列\n", 2428 | "df = pd.DataFrame([dict]).T\n", 2429 | "df = df.reset_index().rename(columns={'index':'id'})\n", 2430 | "df" 2431 | ], 2432 | "outputs": [ 2433 | { 2434 | "output_type": "execute_result", 2435 | "execution_count": 42, 2436 | "data": { 2437 | "text/html": [ 2438 | "
\n", 2439 | "\n", 2452 | "\n", 2453 | " \n", 2454 | " \n", 2455 | " \n", 2456 | " \n", 2457 | " \n", 2458 | " \n", 2459 | " \n", 2460 | " \n", 2461 | " \n", 2462 | " \n", 2463 | " \n", 2464 | " \n", 2465 | " \n", 2466 | " \n", 2467 | " \n", 2468 | " \n", 2469 | " \n", 2470 | " \n", 2471 | " \n", 2472 | "
id0
0aapple
1bbanana
\n", 2473 | "
" 2474 | ], 2475 | "text/plain": [ 2476 | " id 0\n", 2477 | "0 a apple\n", 2478 | "1 b banana" 2479 | ] 2480 | }, 2481 | "metadata": {} 2482 | } 2483 | ], 2484 | "execution_count": 42, 2485 | "metadata": {} 2486 | }, 2487 | { 2488 | "cell_type": "code", 2489 | "source": [ 2490 | "#5.多个值,通过创建子字典\n", 2491 | "test_0 = {\"id\":[1,1,2,3,3,4,5,5],\"price\":[5,6,8,3,4,6,9,5],\"amount\":[1,1,2,1,1,1,2,1],\"status\":['sale','sale','no','no','sale','no','sale','no']} \n", 2492 | "index = {'id','price','amount'} #创建存储想要的key的集合\n", 2493 | "test_1 = {key:value for key,value in test_0.items()if key in index} #建立子字典\n", 2494 | "pd.DataFrame(test_1)" 2495 | ], 2496 | "outputs": [ 2497 | { 2498 | "output_type": "execute_result", 2499 | "execution_count": 73, 2500 | "data": { 2501 | "text/html": [ 2502 | "
\n", 2503 | "\n", 2516 | "\n", 2517 | " \n", 2518 | " \n", 2519 | " \n", 2520 | " \n", 2521 | " \n", 2522 | " \n", 2523 | " \n", 2524 | " \n", 2525 | " \n", 2526 | " \n", 2527 | " \n", 2528 | " \n", 2529 | " \n", 2530 | " \n", 2531 | " \n", 2532 | " \n", 2533 | " \n", 2534 | " \n", 2535 | " \n", 2536 | " \n", 2537 | " \n", 2538 | " \n", 2539 | " \n", 2540 | " \n", 2541 | " \n", 2542 | " \n", 2543 | " \n", 2544 | " \n", 2545 | " \n", 2546 | " \n", 2547 | " \n", 2548 | " \n", 2549 | " \n", 2550 | " \n", 2551 | " \n", 2552 | " \n", 2553 | " \n", 2554 | " \n", 2555 | " \n", 2556 | " \n", 2557 | " \n", 2558 | " \n", 2559 | " \n", 2560 | " \n", 2561 | " \n", 2562 | " \n", 2563 | " \n", 2564 | " \n", 2565 | " \n", 2566 | " \n", 2567 | " \n", 2568 | " \n", 2569 | " \n", 2570 | " \n", 2571 | " \n", 2572 | " \n", 2573 | " \n", 2574 | " \n", 2575 | "
amountidprice
0115
1116
2228
3133
4134
5146
6259
7155
\n", 2576 | "
" 2577 | ], 2578 | "text/plain": [ 2579 | " amount id price\n", 2580 | "0 1 1 5\n", 2581 | "1 1 1 6\n", 2582 | "2 2 2 8\n", 2583 | "3 1 3 3\n", 2584 | "4 1 3 4\n", 2585 | "5 1 4 6\n", 2586 | "6 2 5 9\n", 2587 | "7 1 5 5" 2588 | ] 2589 | }, 2590 | "metadata": {} 2591 | } 2592 | ], 2593 | "execution_count": 73, 2594 | "metadata": { 2595 | "scrolled": true 2596 | } 2597 | }, 2598 | { 2599 | "cell_type": "code", 2600 | "source": [ 2601 | "#根据key 找value \n", 2602 | "d = {'a' : [1, 2, 3], 'b' : [4, 5],'c':[1,2,3,4] }\n", 2603 | "key = ['a','c']\n", 2604 | "value=[]\n", 2605 | "for k in key:\n", 2606 | " value.append(d[k])\n", 2607 | "value" 2608 | ], 2609 | "outputs": [ 2610 | { 2611 | "output_type": "execute_result", 2612 | "execution_count": 64, 2613 | "data": { 2614 | "text/plain": [ 2615 | "[[1, 2, 3], [1, 2, 3, 4]]" 2616 | ] 2617 | }, 2618 | "metadata": {} 2619 | } 2620 | ], 2621 | "execution_count": 64, 2622 | "metadata": {} 2623 | }, 2624 | { 2625 | "cell_type": "code", 2626 | "source": [ 2627 | "#根据value找key\n", 2628 | "d = { 'a' : [1, 2, 3], 'b' : [4, 5],'c':[1,2,3] }\n", 2629 | "value = [1,3]\n", 2630 | "t=[k for k,v in d.items() if v == [1,2,3]]\n", 2631 | "print(t)" 2632 | ], 2633 | "outputs": [ 2634 | { 2635 | "output_type": "stream", 2636 | "name": "stdout", 2637 | "text": [ 2638 | "['a', 'c']\n" 2639 | ] 2640 | } 2641 | ], 2642 | "execution_count": 54, 2643 | "metadata": {} 2644 | }, 2645 | { 2646 | "cell_type": "markdown", 2647 | "source": [ 2648 | "## 4.4 集合\n", 2649 | "集合是无序的不可重复的元素的集合。你可以把它当做字典,但是只有键没有值。" 2650 | ], 2651 | "metadata": {} 2652 | }, 2653 | { 2654 | "cell_type": "code", 2655 | "source": [ 2656 | "#两种方式创建集合:通过set函数或使用尖括号set语句\n", 2657 | "set([2, 2, 2, 1, 3, 3]),{2, 2, 2, 1, 3, 3}" 2658 | ], 2659 | "outputs": [ 2660 | { 2661 | "output_type": "execute_result", 2662 | "execution_count": 16, 2663 | "data": { 2664 | "text/plain": [ 2665 | "({1, 2, 3}, {1, 2, 3})" 2666 | ] 2667 | }, 2668 | "metadata": {} 2669 | } 2670 | ], 2671 | "execution_count": 16, 2672 | "metadata": {} 2673 | }, 2674 | { 2675 | "cell_type": "raw", 2676 | "source": [ 2677 | "集合支持合并、交集、差分和对称差等数学集合运算\n", 2678 | "函数 替代语法 说明\n", 2679 | "a.union(b) a|b 集合a和b中的所有不重复元素\n", 2680 | "a.update(b) al=b 设定集合a中的元素为a与b的合并\n", 2681 | "a.intersection(b) a&b a和b中交叉的元素\n", 2682 | "a.intersection_update(b) a&=b 设定集合a中的元素为a与b的交叉\n", 2683 | "a.difference(b) a-b 存在于a但不存在于b的元素\n", 2684 | "a.difference_update(b) a-=b 设定集合a中的元素为a与b的差\n", 2685 | "a.symmetric_difference(b) a^b 只在a或只在b的元素\n", 2686 | "a.symmetric_difference_update(b) a^=b 集合a中的元素为只在a或只在b的元素" 2687 | ], 2688 | "metadata": {} 2689 | }, 2690 | { 2691 | "cell_type": "code", 2692 | "source": [ 2693 | "a = {1, 2, 3, 4, 5}\n", 2694 | "b = {3, 4, 5, 6, 7, 8}\n", 2695 | "a.union(b),a.intersection(b)" 2696 | ], 2697 | "outputs": [ 2698 | { 2699 | "output_type": "execute_result", 2700 | "execution_count": 18, 2701 | "data": { 2702 | "text/plain": [ 2703 | "({1, 2, 3, 4, 5, 6, 7, 8}, {3, 4, 5})" 2704 | ] 2705 | }, 2706 | "metadata": {} 2707 | } 2708 | ], 2709 | "execution_count": 18, 2710 | "metadata": {} 2711 | }, 2712 | { 2713 | "cell_type": "code", 2714 | "source": [ 2715 | "c = a.copy()\n", 2716 | "c |= b\n", 2717 | "c" 2718 | ], 2719 | "outputs": [ 2720 | { 2721 | "output_type": "execute_result", 2722 | "execution_count": 19, 2723 | "data": { 2724 | "text/plain": [ 2725 | "{1, 2, 3, 4, 5, 6, 7, 8}" 2726 | ] 2727 | }, 2728 | "metadata": {} 2729 | } 2730 | ], 2731 | "execution_count": 19, 2732 | "metadata": {} 2733 | }, 2734 | { 2735 | "cell_type": "code", 2736 | "source": [ 2737 | "d = a.copy()\n", 2738 | "d &= b\n", 2739 | "d" 2740 | ], 2741 | "outputs": [ 2742 | { 2743 | "output_type": "execute_result", 2744 | "execution_count": 20, 2745 | "data": { 2746 | "text/plain": [ 2747 | "{3, 4, 5}" 2748 | ] 2749 | }, 2750 | "metadata": {} 2751 | } 2752 | ], 2753 | "execution_count": 20, 2754 | "metadata": {} 2755 | }, 2756 | { 2757 | "cell_type": "markdown", 2758 | "source": [ 2759 | "## 4.5常用序列函数" 2760 | ], 2761 | "metadata": {} 2762 | }, 2763 | { 2764 | "cell_type": "markdown", 2765 | "source": [ 2766 | "### enumerate函数" 2767 | ], 2768 | "metadata": {} 2769 | }, 2770 | { 2771 | "cell_type": "raw", 2772 | "source": [ 2773 | "enumerate() 函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中。 enumerate(sequence, [start=0])\n", 2774 | "sequence 一个序列、迭代器或其他支持迭代对象。\n", 2775 | "start 下标起始位置。" 2776 | ], 2777 | "metadata": {} 2778 | }, 2779 | { 2780 | "cell_type": "code", 2781 | "source": [ 2782 | "seasons = ['Spring','Summer','Fall','Winter']\n", 2783 | "for i,ele in enumerate(seasons):\n", 2784 | " print(i,ele)" 2785 | ], 2786 | "outputs": [ 2787 | { 2788 | "output_type": "stream", 2789 | "name": "stdout", 2790 | "text": [ 2791 | "0 Spring\n", 2792 | "1 Summer\n", 2793 | "2 Fall\n", 2794 | "3 Winter\n" 2795 | ] 2796 | } 2797 | ], 2798 | "execution_count": 124, 2799 | "metadata": {} 2800 | }, 2801 | { 2802 | "cell_type": "markdown", 2803 | "source": [ 2804 | "### sorted函数\n", 2805 | "sorted函数可以从任意序列的元素返回一个新的排好序的列表" 2806 | ], 2807 | "metadata": {} 2808 | }, 2809 | { 2810 | "cell_type": "code", 2811 | "source": [ 2812 | "sorted([7, 1, 2, 6, 0, 3, 2]),sorted('horse race')" 2813 | ], 2814 | "outputs": [ 2815 | { 2816 | "output_type": "execute_result", 2817 | "execution_count": 126, 2818 | "data": { 2819 | "text/plain": [ 2820 | "([0, 1, 2, 2, 3, 6, 7], [' ', 'a', 'c', 'e', 'e', 'h', 'o', 'r', 'r', 's'])" 2821 | ] 2822 | }, 2823 | "metadata": {} 2824 | } 2825 | ], 2826 | "execution_count": 126, 2827 | "metadata": {} 2828 | }, 2829 | { 2830 | "cell_type": "markdown", 2831 | "source": [ 2832 | "### zip函数\n", 2833 | "zip可以将多个列表、元组或其它序列成对组合成一个元组列表.zip可以处理任意多的序列,元素的个数取决于最短的序列" 2834 | ], 2835 | "metadata": {} 2836 | }, 2837 | { 2838 | "cell_type": "code", 2839 | "source": [ 2840 | "seq1 = ['foo', 'bar', 'baz']\n", 2841 | "\n", 2842 | "seq2 = ['one', 'two', 'three']\n", 2843 | "\n", 2844 | "zipped = zip(seq1, seq2)\n", 2845 | "\n", 2846 | "list(zipped)" 2847 | ], 2848 | "outputs": [ 2849 | { 2850 | "output_type": "execute_result", 2851 | "execution_count": 1, 2852 | "data": { 2853 | "text/plain": [ 2854 | "[('foo', 'one'), ('bar', 'two'), ('baz', 'three')]" 2855 | ] 2856 | }, 2857 | "metadata": {} 2858 | } 2859 | ], 2860 | "execution_count": 1, 2861 | "metadata": {} 2862 | }, 2863 | { 2864 | "cell_type": "code", 2865 | "source": [ 2866 | "seq3 = [False, True]\n", 2867 | "list(zip(seq1, seq2, seq3))" 2868 | ], 2869 | "outputs": [ 2870 | { 2871 | "output_type": "execute_result", 2872 | "execution_count": 2, 2873 | "data": { 2874 | "text/plain": [ 2875 | "[('foo', 'one', False), ('bar', 'two', True)]" 2876 | ] 2877 | }, 2878 | "metadata": {} 2879 | } 2880 | ], 2881 | "execution_count": 2, 2882 | "metadata": {} 2883 | }, 2884 | { 2885 | "cell_type": "code", 2886 | "source": [ 2887 | "#zip的常见用法之一是同时迭代多个序列,可能结合enumerate使用\n", 2888 | "for i, (a, b) in enumerate(zip(seq1, seq2)):\n", 2889 | " print('{0}: {1}, {2}'.format(i, a, b))" 2890 | ], 2891 | "outputs": [ 2892 | { 2893 | "output_type": "stream", 2894 | "name": "stdout", 2895 | "text": [ 2896 | "0: foo, one\n", 2897 | "1: bar, two\n", 2898 | "2: baz, three\n" 2899 | ] 2900 | } 2901 | ], 2902 | "execution_count": 3, 2903 | "metadata": {} 2904 | }, 2905 | { 2906 | "cell_type": "markdown", 2907 | "source": [ 2908 | "### reversed函数" 2909 | ], 2910 | "metadata": {} 2911 | }, 2912 | { 2913 | "cell_type": "code", 2914 | "source": [ 2915 | "list(reversed(range(10)))#reversed可以从后向前迭代一个序列" 2916 | ], 2917 | "outputs": [ 2918 | { 2919 | "output_type": "execute_result", 2920 | "execution_count": 4, 2921 | "data": { 2922 | "text/plain": [ 2923 | "[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]" 2924 | ] 2925 | }, 2926 | "metadata": {} 2927 | } 2928 | ], 2929 | "execution_count": 4, 2930 | "metadata": {} 2931 | }, 2932 | { 2933 | "cell_type": "code", 2934 | "source": [ 2935 | "help(\"keywords\")" 2936 | ], 2937 | "outputs": [ 2938 | { 2939 | "output_type": "stream", 2940 | "name": "stdout", 2941 | "text": [ 2942 | "\n", 2943 | "Here is a list of the Python keywords. Enter any keyword to get more help.\n", 2944 | "\n", 2945 | "False def if raise\n", 2946 | "None del import return\n", 2947 | "True elif in try\n", 2948 | "and else is while\n", 2949 | "as except lambda with\n", 2950 | "assert finally nonlocal yield\n", 2951 | "break for not \n", 2952 | "class from or \n", 2953 | "continue global pass \n", 2954 | "\n" 2955 | ] 2956 | } 2957 | ], 2958 | "execution_count": 23, 2959 | "metadata": {} 2960 | }, 2961 | { 2962 | "cell_type": "raw", 2963 | "source": [ 2964 | " x and y 如果 x 为 False 、空、0,返 回 x,否则返回 y\n", 2965 | " x or y 如果 x 为 False、 空、0,返回 y,否则返回x\n", 2966 | " not x 如果 x 为 False、 空、0,返回 True,否则返回False" 2967 | ], 2968 | "metadata": {} 2969 | }, 2970 | { 2971 | "cell_type": "code", 2972 | "source": [ 2973 | "a = '1'\n", 2974 | "b = 1\n", 2975 | "a and b,a or y,not a" 2976 | ], 2977 | "outputs": [ 2978 | { 2979 | "output_type": "execute_result", 2980 | "execution_count": 28, 2981 | "data": { 2982 | "text/plain": [ 2983 | "(1, '1', False)" 2984 | ] 2985 | }, 2986 | "metadata": {} 2987 | } 2988 | ], 2989 | "execution_count": 28, 2990 | "metadata": {} 2991 | }, 2992 | { 2993 | "cell_type": "code", 2994 | "source": [], 2995 | "outputs": [], 2996 | "execution_count": null, 2997 | "metadata": { 2998 | "collapsed": true 2999 | } 3000 | } 3001 | ], 3002 | "metadata": { 3003 | "kernelspec": { 3004 | "name": "python3", 3005 | "language": "python", 3006 | "display_name": "Python 3" 3007 | }, 3008 | "language_info": { 3009 | "name": "python", 3010 | "version": "3.6.1", 3011 | "mimetype": "text/x-python", 3012 | "codemirror_mode": { 3013 | "name": "ipython", 3014 | "version": 3 3015 | }, 3016 | "pygments_lexer": "ipython3", 3017 | "nbconvert_exporter": "python", 3018 | "file_extension": ".py" 3019 | }, 3020 | "varInspector": { 3021 | "cols": { 3022 | "lenName": 16, 3023 | "lenType": 16, 3024 | "lenVar": 40 3025 | }, 3026 | "kernels_config": { 3027 | "python": { 3028 | "delete_cmd_postfix": "", 3029 | "delete_cmd_prefix": "del ", 3030 | "library": "var_list.py", 3031 | "varRefreshCmd": "print(var_dic_list())" 3032 | }, 3033 | "r": { 3034 | "delete_cmd_postfix": ") ", 3035 | "delete_cmd_prefix": "rm(", 3036 | "library": "var_list.r", 3037 | "varRefreshCmd": "cat(var_dic_list()) " 3038 | } 3039 | }, 3040 | "types_to_exclude": [ 3041 | "module", 3042 | "function", 3043 | "builtin_function_or_method", 3044 | "instance", 3045 | "_Feature" 3046 | ], 3047 | "window_display": false 3048 | }, 3049 | "kernel_info": { 3050 | "name": "python3" 3051 | }, 3052 | "nteract": { 3053 | "version": "0.14.5" 3054 | } 3055 | }, 3056 | "nbformat": 4, 3057 | "nbformat_minor": 2 3058 | } -------------------------------------------------------------------------------- /1 python基础语法.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetalkdata/python_script-manual/4720aec496fe9b6f2b5e5fa92cf6aace864aac82/1 python基础语法.pdf -------------------------------------------------------------------------------- /2 pandas用法.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetalkdata/python_script-manual/4720aec496fe9b6f2b5e5fa92cf6aace864aac82/2 pandas用法.pdf -------------------------------------------------------------------------------- /3 Numpy计算.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# 第3章 numpy计算\n", 8 | "NumPy(Numerical Python的简称)是高性能科学计算和数据分析的基础包。部分功能如下:\n", 9 | "\n", 10 | "* ndarray,一个具有矢量算术运算和复杂广播能力的快速且节省空间的多维数组。\n", 11 | "* 用于对整组数据进行快速运算的标准数学函数(无需编写循环)。\n", 12 | "* 用于读写磁盘数据的工具以及用于操作内存映射文件的工具。\n", 13 | "* 线性代数、随机数生成以及傅里叶变换功能。\n", 14 | "* 用于集成由C、C++、Fortran等语言编写的代码的工具。\n", 15 | "\n", 16 | "最后一点也是从生态系统角度来看最重要的一点。由于NumPy提供了一个简单易用的C API,因此很容易将数据传递给由低级语言编写的外部库,外部库也能以NumPy数组的形式将数据返回给Python。这个功能使Python成为一种包装C/C++/Fortran历史代码库的选择,并使被包装库拥有一个动态的、易用的接口。" 17 | ] 18 | }, 19 | { 20 | "cell_type": "markdown", 21 | "metadata": {}, 22 | "source": [ 23 | " 本章主要分为以下几个部分进行介绍:\n", 24 | " \n", 25 | "一、NumPy的ndarray\n", 26 | "* 创建ndarray\n", 27 | "* ndarray的数据类型\n", 28 | "* ndarray 对象常用方法\n", 29 | "* 基本的切片与索引\n", 30 | "* 高级索引\n", 31 | "* 整数索引\n", 32 | "* 布尔索引\n", 33 | "* 花式索引\n", 34 | "* 按条件返回索引\n", 35 | "二、通用函数:快速的元素级数组函数\n", 36 | "* 一元通用函数\n", 37 | "* 二元通用函数\n", 38 | "* 执行特定矢量化运算的特殊ufunc方法\n", 39 | "三、统计方法\n", 40 | "四、排序\n", 41 | "五、数据的唯一化和集合运算\n", 42 | "六、随机数生成\n", 43 | "七、NumPy 矩阵库(Matrix)及其计算\n", 44 | "* 创建矩阵\n", 45 | "* 矩阵运算\n", 46 | "八、高级数组操作\n", 47 | "* 反转、转置数组\n", 48 | "* 数组重塑\n", 49 | "* 数组的合并和拆分\n", 50 | "* 数组元素的添加与删除\n", 51 | "九、广播" 52 | ] 53 | }, 54 | { 55 | "cell_type": "code", 56 | "execution_count": 1, 57 | "metadata": { 58 | "collapsed": true 59 | }, 60 | "outputs": [], 61 | "source": [ 62 | "import numpy.matlib \n", 63 | "import numpy as np\n", 64 | "import pandas as pd" 65 | ] 66 | }, 67 | { 68 | "cell_type": "markdown", 69 | "metadata": {}, 70 | "source": [ 71 | "# 一、NumPy的ndarray\n", 72 | "一种多维数组对象NumPy最重要的一个特点就是其N维数组对象(即ndarray),该对象是一个快速而灵活的大数据集容器。本部分主要介绍ndarray以及基本的切片与索引。" 73 | ] 74 | }, 75 | { 76 | "cell_type": "raw", 77 | "metadata": {}, 78 | "source": [ 79 | "ndarray是一系列同类型数据的集合,以 0 下标为开始进行集合中元素的索引。\n", 80 | "ndarray 对象是用于存放同类型元素的多维数组。ndarray 中的每个元素在内存中都有相同存储大小的区域。" 81 | ] 82 | }, 83 | { 84 | "cell_type": "markdown", 85 | "metadata": {}, 86 | "source": [ 87 | "## 创建ndarray" 88 | ] 89 | }, 90 | { 91 | "cell_type": "raw", 92 | "metadata": {}, 93 | "source": [ 94 | "创建数组最简单的办法就是使用array函数。它接受一切序列型的对象(包括其他数组),然后产生一个新的含有传入数据的NumPy数组。\n", 95 | "numpy.array(object, dtype = None, copy = True, order = None, subok = False, ndmin = 0)\n", 96 | "参数说明:\n", 97 | "object:数组或嵌套的数列\n", 98 | "dtype:数组元素的数据类型,可选\n", 99 | "copy:对象是否需要复制,可选\n", 100 | "order:创建数组的样式,C为行方向,F为列方向,A为任意方向(默认)\n", 101 | "subok:默认返回一个与基类类型一致的数组\n", 102 | "ndmin:指定生成数组的最小维度\n", 103 | "一般情况下前两个参数是必须有的,其余参数较少使用。" 104 | ] 105 | }, 106 | { 107 | "cell_type": "code", 108 | "execution_count": 5, 109 | "metadata": {}, 110 | "outputs": [ 111 | { 112 | "data": { 113 | "text/plain": [ 114 | "array([6. , 7.5, 8. , 0. , 1. ])" 115 | ] 116 | }, 117 | "execution_count": 5, 118 | "metadata": {}, 119 | "output_type": "execute_result" 120 | } 121 | ], 122 | "source": [ 123 | "data1=[6,7.5,8,0,1]\n", 124 | "arr1=np.array(data1)\n", 125 | "arr1" 126 | ] 127 | }, 128 | { 129 | "cell_type": "raw", 130 | "metadata": {}, 131 | "source": [ 132 | "除此之外还有一些函数也可以创建ndarray\n", 133 | "从已有数组创建: numpy.asarray(a, dtype = None, order = None)\n", 134 | "未初始化数组:numpy.empty(shape, dtype = float, order = 'C')\n", 135 | "全0数组:numpy.zeros(shape, dtype = float, order = 'C')\n", 136 | "全1数组:numpy.ones(shape, dtype = None, order = 'C')\n", 137 | "数值范围数组:numpy.arange(start, stop, step, dtype)\n", 138 | "对角数组:numpy.eye(N, M=None, k=0, dtype=, order='C')\n", 139 | "其中: \n", 140 | "shape: 数组形状 \n", 141 | "dtype: 数据类型\n", 142 | "order: C和F,分别代表行优先和列优先。 \n", 143 | "start: 起始值,默认为0 \n", 144 | "stop: 终止值(不包含) \n", 145 | "step: 步长,默认为1 \n", 146 | "dtype: 返回ndarray的数据类型,默认使用输入数据的类型。 \n", 147 | "num: 要生成的等步长的样本数量,默认为50" 148 | ] 149 | }, 150 | { 151 | "cell_type": "code", 152 | "execution_count": 7, 153 | "metadata": {}, 154 | "outputs": [ 155 | { 156 | "name": "stdout", 157 | "output_type": "stream", 158 | "text": [ 159 | "np.zeros((2,2)):\n", 160 | " [[0. 0.]\n", 161 | " [0. 0.]]\n", 162 | "np.ones((2,2)):\n", 163 | " [[1. 1.]\n", 164 | " [1. 1.]]\n", 165 | "np.eye((2)):\n", 166 | " [[1. 0.]\n", 167 | " [0. 1.]]\n", 168 | "np.random.random((2,2)):\n", 169 | " [[0.57223409 0.08745789]\n", 170 | " [0.54097632 0.87183112]]\n" 171 | ] 172 | } 173 | ], 174 | "source": [ 175 | "print (\"np.zeros((2,2)):\\n\", np.zeros((2,2)))\n", 176 | "print (\"np.ones((2,2)):\\n\", np.ones((2,2)))\n", 177 | "print (\"np.eye((2)):\\n\", np.eye((2)))\n", 178 | "print (\"np.random.random((2,2)):\\n\", np.random.random((2,2)))" 179 | ] 180 | }, 181 | { 182 | "cell_type": "markdown", 183 | "metadata": {}, 184 | "source": [ 185 | "## ndarray的数据类型\n", 186 | "dtype(数据类型)是一个特殊的对象,它含有ndaray将一块内存解释为特定数据类型所需的信息:" 187 | ] 188 | }, 189 | { 190 | "cell_type": "code", 191 | "execution_count": 8, 192 | "metadata": {}, 193 | "outputs": [ 194 | { 195 | "name": "stdout", 196 | "output_type": "stream", 197 | "text": [ 198 | "float64 int32\n" 199 | ] 200 | } 201 | ], 202 | "source": [ 203 | "arr1=np. array([1,2,3], dtype=np. float64)\n", 204 | "arr2=np. array([1,2,3], dtype=np. int32)\n", 205 | "print(arr1.dtype,arr2.dtype)" 206 | ] 207 | }, 208 | { 209 | "cell_type": "code", 210 | "execution_count": 11, 211 | "metadata": {}, 212 | "outputs": [ 213 | { 214 | "name": "stdout", 215 | "output_type": "stream", 216 | "text": [ 217 | "int32\n", 218 | "float64\n" 219 | ] 220 | } 221 | ], 222 | "source": [ 223 | "#你可以通过ndarray的astype方法显式地转换其dtype\n", 224 | "arr=np.array([1,2,3,4,5])\n", 225 | "print(arr.dtype)\n", 226 | "float_arr=arr.astype(np.float64)\n", 227 | "print(float_arr.dtype)" 228 | ] 229 | }, 230 | { 231 | "cell_type": "markdown", 232 | "metadata": {}, 233 | "source": [ 234 | "## ndarray 对象常用方法" 235 | ] 236 | }, 237 | { 238 | "cell_type": "raw", 239 | "metadata": {}, 240 | "source": [ 241 | "ndarray.ndim: 秩,即轴的数量或维度的数量\n", 242 | "ndarray.shape: 数组的维度,对于矩阵,n 行 m 列\n", 243 | "ndarray.size: 数组元素的总个数,相当于 .shape 中 n*m 的值\n", 244 | "ndarray.dtype: ndarray 对象的元素类型\n", 245 | "ndarray.tolist: narray对象转化为list\n", 246 | "ndarray.newaxis:给原数组增加一个维度" 247 | ] 248 | }, 249 | { 250 | "cell_type": "code", 251 | "execution_count": 13, 252 | "metadata": {}, 253 | "outputs": [ 254 | { 255 | "name": "stdout", 256 | "output_type": "stream", 257 | "text": [ 258 | "x ndim: 1\n", 259 | "x shape: (5,)\n", 260 | "x size: 5\n", 261 | "x dtype: int32\n" 262 | ] 263 | } 264 | ], 265 | "source": [ 266 | "x=np.array([1,2,3,4,5])\n", 267 | "# 秩\n", 268 | "print (\"x ndim: \", x.ndim)\n", 269 | "# 维度\n", 270 | "print (\"x shape:\", x.shape)\n", 271 | "# 数组元素的总个数\n", 272 | "print (\"x size: \", x.size)\n", 273 | "# ndarray 对象的元素类型\n", 274 | "print (\"x dtype: \", x.dtype)" 275 | ] 276 | }, 277 | { 278 | "cell_type": "code", 279 | "execution_count": 14, 280 | "metadata": {}, 281 | "outputs": [ 282 | { 283 | "name": "stdout", 284 | "output_type": "stream", 285 | "text": [ 286 | "x: [1.3 2.2 1.7]\n", 287 | "x ndim: 1\n", 288 | "x shape: (3,)\n", 289 | "x size: 3\n", 290 | "x dtype: float64\n" 291 | ] 292 | } 293 | ], 294 | "source": [ 295 | "# 1-D \n", 296 | "x = np.array([1.3 , 2.2 , 1.7])\n", 297 | "print (\"x: \", x)\n", 298 | "print (\"x ndim: \", x.ndim)\n", 299 | "print (\"x shape:\", x.shape)\n", 300 | "print (\"x size: \", x.size)\n", 301 | "print (\"x dtype: \", x.dtype) # 注意 float datatype" 302 | ] 303 | }, 304 | { 305 | "cell_type": "code", 306 | "execution_count": 15, 307 | "metadata": {}, 308 | "outputs": [ 309 | { 310 | "name": "stdout", 311 | "output_type": "stream", 312 | "text": [ 313 | "x:\n", 314 | " [[[1 2 3]\n", 315 | " [4 5 6]\n", 316 | " [7 8 9]]]\n", 317 | "x ndim: 3\n", 318 | "x shape: (1, 3, 3)\n", 319 | "x size: 9\n", 320 | "x dtype: int32\n" 321 | ] 322 | } 323 | ], 324 | "source": [ 325 | "# 3-D (矩阵)\n", 326 | "x = np.array([[[1,2,3], [4,5,6], [7,8,9]]])\n", 327 | "print (\"x:\\n\", x)\n", 328 | "print (\"x ndim: \", x.ndim)\n", 329 | "print (\"x shape:\", x.shape)\n", 330 | "print (\"x size: \", x.size)\n", 331 | "print (\"x dtype: \", x.dtype)" 332 | ] 333 | }, 334 | { 335 | "cell_type": "code", 336 | "execution_count": 16, 337 | "metadata": {}, 338 | "outputs": [ 339 | { 340 | "data": { 341 | "text/plain": [ 342 | "(array([1, 2]), [1, 2])" 343 | ] 344 | }, 345 | "execution_count": 16, 346 | "metadata": {}, 347 | "output_type": "execute_result" 348 | } 349 | ], 350 | "source": [ 351 | "#array转化为list\n", 352 | "a = np.array([1,2])\n", 353 | "b = a.tolist()\n", 354 | "a,b" 355 | ] 356 | }, 357 | { 358 | "cell_type": "code", 359 | "execution_count": 17, 360 | "metadata": {}, 361 | "outputs": [ 362 | { 363 | "data": { 364 | "text/plain": [ 365 | "(array([2, 1, 2, 6, 4]), array([[2, 1, 2, 6, 4]]))" 366 | ] 367 | }, 368 | "execution_count": 17, 369 | "metadata": {}, 370 | "output_type": "execute_result" 371 | } 372 | ], 373 | "source": [ 374 | "#增加一个维度 []→[[]]\n", 375 | "x = np.random.randint(1, 8, size=5)\n", 376 | "x1 = x[np.newaxis, :]\n", 377 | "x,x1" 378 | ] 379 | }, 380 | { 381 | "cell_type": "markdown", 382 | "metadata": {}, 383 | "source": [ 384 | "## 基本的切片与索引" 385 | ] 386 | }, 387 | { 388 | "cell_type": "raw", 389 | "metadata": {}, 390 | "source": [ 391 | "ndarray对象的内容可以通过索引或切片来访问和修改。\n", 392 | "与 Python 中 list 的切片操作一样,ndarray 数组可以基于 0 - n 的下标进行索引,切片对象可以通过内置的 slice 函数从原数组中切割出一个新数组。\n", 393 | "slice(start,stop , step )" 394 | ] 395 | }, 396 | { 397 | "cell_type": "code", 398 | "execution_count": 18, 399 | "metadata": {}, 400 | "outputs": [ 401 | { 402 | "name": "stdout", 403 | "output_type": "stream", 404 | "text": [ 405 | "x[0]: 1\n", 406 | "x: [0 2 3]\n" 407 | ] 408 | } 409 | ], 410 | "source": [ 411 | "# 索引\n", 412 | "x = np.array([1, 2, 3])\n", 413 | "print (\"x[0]: \", x[0])\n", 414 | "x[0] = 0\n", 415 | "print (\"x: \", x)" 416 | ] 417 | }, 418 | { 419 | "cell_type": "code", 420 | "execution_count": 19, 421 | "metadata": {}, 422 | "outputs": [ 423 | { 424 | "name": "stdout", 425 | "output_type": "stream", 426 | "text": [ 427 | "[0 1 2 3 4 5 6 7 8 9]\n", 428 | "[2 4 6]\n" 429 | ] 430 | } 431 | ], 432 | "source": [ 433 | "# slice函数切片\n", 434 | "a = np.arange(10)\n", 435 | "print(a)\n", 436 | "s = slice(2,7,2) # 从索引2开始到索引7停止 , 间隔为2\n", 437 | "print (a[s])" 438 | ] 439 | }, 440 | { 441 | "cell_type": "code", 442 | "execution_count": 20, 443 | "metadata": {}, 444 | "outputs": [ 445 | { 446 | "name": "stdout", 447 | "output_type": "stream", 448 | "text": [ 449 | "[[ 1 2 3 4]\n", 450 | " [ 5 6 7 8]\n", 451 | " [ 9 10 11 12]]\n", 452 | "x column 1: [ 2 6 10]\n", 453 | "x row 0: [1 2 3 4]\n", 454 | "x rows 0,1,2 & cols 1,2: \n", 455 | " [[ 2 3]\n", 456 | " [ 6 7]\n", 457 | " [10 11]]\n" 458 | ] 459 | } 460 | ], 461 | "source": [ 462 | "# 切片\n", 463 | "#冒号 :的解释\n", 464 | "#如果只放置一个参数,如 [1],将返回与该索引相对应的单个元素。\n", 465 | "#如果为 [1:],表示从该索引[1]开始以后的所有项都将被提取。\n", 466 | "#如果使用了两个参数,如 [1:3],那么则提取两个索引(不包括停止索引)之间的项,即[1][2]\n", 467 | "x = np.array([[1,2,3,4], [5,6,7,8], [9,10,11,12]])\n", 468 | "print (x)\n", 469 | "print (\"x column 1: \", x[:, 1]) \n", 470 | "print (\"x row 0: \", x[0, :]) \n", 471 | "print (\"x rows 0,1,2 & cols 1,2: \\n\", x[:3, 1:3])" 472 | ] 473 | }, 474 | { 475 | "cell_type": "markdown", 476 | "metadata": {}, 477 | "source": [ 478 | "## 高级索引" 479 | ] 480 | }, 481 | { 482 | "cell_type": "raw", 483 | "metadata": {}, 484 | "source": [ 485 | "NumPy 比一般的 Python 序列提供更多的索引方式。除了用整数和切片的索引外,数组可以由整数数组索引、布尔索引等。\n", 486 | "\n", 487 | "布尔索引通过布尔运算(如:比较运算符)来获取符合指定条件的元素的数组。\n", 488 | "\n", 489 | "花式索引根据索引数组的值作为目标数组的某个轴的下标来取值。对于使用一维整型数组作为索引,如果目标是一维数组,那么索引的结果就是对应位置的元素;如果目标是二维数组,那么就是对应下标的行。花式索引跟切片不一样,它总是将数据复制到新数组中。" 490 | ] 491 | }, 492 | { 493 | "cell_type": "markdown", 494 | "metadata": {}, 495 | "source": [ 496 | "### 整数索引" 497 | ] 498 | }, 499 | { 500 | "cell_type": "code", 501 | "execution_count": 21, 502 | "metadata": {}, 503 | "outputs": [ 504 | { 505 | "name": "stdout", 506 | "output_type": "stream", 507 | "text": [ 508 | "[[ 1 2 3 4]\n", 509 | " [ 5 6 7 8]\n", 510 | " [ 9 10 11 12]]\n", 511 | "rows_to_get: [0 1 2]\n", 512 | "cols_to_get: [0 2 1]\n", 513 | "indexed values: [ 1 7 10]\n" 514 | ] 515 | } 516 | ], 517 | "source": [ 518 | "print (x)\n", 519 | "rows_to_get = np.arange(len(x))\n", 520 | "print (\"rows_to_get: \", rows_to_get)\n", 521 | "cols_to_get = np.array([0, 2, 1])\n", 522 | "print (\"cols_to_get: \", cols_to_get)\n", 523 | "print (\"indexed values: \", x[rows_to_get, cols_to_get])" 524 | ] 525 | }, 526 | { 527 | "cell_type": "markdown", 528 | "metadata": {}, 529 | "source": [ 530 | "### 布尔索引" 531 | ] 532 | }, 533 | { 534 | "cell_type": "code", 535 | "execution_count": 22, 536 | "metadata": {}, 537 | "outputs": [ 538 | { 539 | "name": "stdout", 540 | "output_type": "stream", 541 | "text": [ 542 | "x:\n", 543 | " [[1 2]\n", 544 | " [3 4]\n", 545 | " [5 6]]\n", 546 | "x > 2:\n", 547 | " [[False False]\n", 548 | " [ True True]\n", 549 | " [ True True]]\n", 550 | "x[x > 2]:\n", 551 | " [3 4 5 6]\n" 552 | ] 553 | } 554 | ], 555 | "source": [ 556 | "# 布尔值索引\n", 557 | "x = np.array([[1,2], [3, 4], [5, 6]])\n", 558 | "print (\"x:\\n\", x)\n", 559 | "print (\"x > 2:\\n\", x > 2)\n", 560 | "print (\"x[x > 2]:\\n\", x[x > 2])" 561 | ] 562 | }, 563 | { 564 | "cell_type": "markdown", 565 | "metadata": {}, 566 | "source": [ 567 | "### 花式索引" 568 | ] 569 | }, 570 | { 571 | "cell_type": "code", 572 | "execution_count": 23, 573 | "metadata": {}, 574 | "outputs": [ 575 | { 576 | "name": "stdout", 577 | "output_type": "stream", 578 | "text": [ 579 | "x:\n", 580 | " [[ 0 1 2 3]\n", 581 | " [ 4 5 6 7]\n", 582 | " [ 8 9 10 11]\n", 583 | " [12 13 14 15]\n", 584 | " [16 17 18 19]\n", 585 | " [20 21 22 23]\n", 586 | " [24 25 26 27]\n", 587 | " [28 29 30 31]]\n", 588 | "传入顺序索引数组:\n", 589 | " [[16 17 18 19]\n", 590 | " [ 8 9 10 11]\n", 591 | " [ 4 5 6 7]\n", 592 | " [28 29 30 31]]\n", 593 | "传入倒序索引数组:\n", 594 | " [[16 17 18 19]\n", 595 | " [24 25 26 27]\n", 596 | " [28 29 30 31]\n", 597 | " [ 4 5 6 7]]\n", 598 | "传入多个索引数组:\n", 599 | " [[ 4 7 5 6]\n", 600 | " [20 23 21 22]\n", 601 | " [28 31 29 30]\n", 602 | " [ 8 11 9 10]]\n" 603 | ] 604 | } 605 | ], 606 | "source": [ 607 | "# 花式索引\n", 608 | "x=np.arange(32).reshape((8,4))\n", 609 | "print(\"x:\\n\",x)\n", 610 | "print (\"传入顺序索引数组:\\n\",x[[4,2,1,7]])\n", 611 | "print (\"传入倒序索引数组:\\n\",x[[-4,-2,-1,-7]])\n", 612 | "print (\"传入多个索引数组:\\n\",x[np.ix_([1,5,7,2],[0,3,1,2])])" 613 | ] 614 | }, 615 | { 616 | "cell_type": "markdown", 617 | "metadata": {}, 618 | "source": [ 619 | "### 按照条件返回索引" 620 | ] 621 | }, 622 | { 623 | "cell_type": "raw", 624 | "metadata": {}, 625 | "source": [ 626 | "numpy.argmax() 和 numpy.argmin()函数分别沿给定轴返回最大和最小元素的索引。\n", 627 | "numpy.nonzero() 函数返回输入数组中非零元素的索引。\n", 628 | "numpy.where() 函数返回输入数组中满足给定条件的元素的索引。" 629 | ] 630 | }, 631 | { 632 | "cell_type": "code", 633 | "execution_count": 24, 634 | "metadata": {}, 635 | "outputs": [ 636 | { 637 | "name": "stdout", 638 | "output_type": "stream", 639 | "text": [ 640 | "数组展开最大元素的索引: 7\n", 641 | "数组按列最大元素的索引: [1 2 0]\n", 642 | "数组按行最大元素的索引: [2 0 1]\n", 643 | "数组展开最大元素的索引: 5\n", 644 | "数组按列最大元素的索引: [0 1 1]\n", 645 | "数组按行最大元素的索引: [0 2 0]\n", 646 | "数组中非零元素的索引: (array([0, 0, 0, 1, 1, 1, 2, 2, 2], dtype=int64), array([0, 1, 2, 0, 1, 2, 0, 1, 2], dtype=int64))\n", 647 | "数组中大于50的索引: (array([0, 1, 2, 2], dtype=int64), array([2, 0, 1, 2], dtype=int64))\n", 648 | "使用这些索引来获取满足条件的元素: [70 80 90 60]\n" 649 | ] 650 | } 651 | ], 652 | "source": [ 653 | "a = np.array([[30,40,70],[80,20,10],[50,90,60]])\n", 654 | "print (\"数组展开最大元素的索引:\",np.argmax(a)) \n", 655 | "print (\"数组按列最大元素的索引:\",np.argmax(a, axis = 0)) \n", 656 | "print (\"数组按行最大元素的索引:\",np.argmax(a, axis = 1)) \n", 657 | "print (\"数组展开最大元素的索引:\",np.argmin(a)) \n", 658 | "print (\"数组按列最大元素的索引:\",np.argmin(a, axis = 0)) \n", 659 | "print (\"数组按行最大元素的索引:\",np.argmin(a, axis = 1))\n", 660 | "print (\"数组中非零元素的索引:\",np.nonzero (a))\n", 661 | "print (\"数组中大于50的索引:\",np.where(a > 50))\n", 662 | "print ('使用这些索引来获取满足条件的元素:',a[np.where(a > 50)])" 663 | ] 664 | }, 665 | { 666 | "cell_type": "markdown", 667 | "metadata": {}, 668 | "source": [ 669 | "# 二、通用函数:快速的元素级数组函数\n", 670 | "通用函数(即ufunc)是一种对ndarray中的数据执行元素级运算的函数。你可以将其看做简单函数(接受一个或多个标量值,并产生一个或多个标量值)的矢量化包装器。本部分主要介绍一元、二元通用函数以及执行特定矢量化运算的特殊方法。" 671 | ] 672 | }, 673 | { 674 | "cell_type": "markdown", 675 | "metadata": {}, 676 | "source": [ 677 | "## 一元通用函数" 678 | ] 679 | }, 680 | { 681 | "cell_type": "raw", 682 | "metadata": {}, 683 | "source": [ 684 | "abs、fabs 计算整数、浮点数或复数的绝对值。对于非复数值,可以使用更快的fabs\n", 685 | "sqrt 计算各元素的平方根。相当于arr**0.5\n", 686 | "square 计算各元素的平方。相当于arr**2\n", 687 | "exp 计算各元素的指数e \n", 688 | "log、log10、log2、loglp 分别为自然对数(底数为e)、底数为10的1og、底数为2的log、log(1+x)\n", 689 | "sign 计算各元素的正负号:1(正数)、0(零)、-1(负数)\n", 690 | "ceil 计算各元素的ceiling值,即大于等于该值的最小整数\n", 691 | "floor 计算各元素的floor值,即小于等于该值的最大整数\n", 692 | "rint 将各元素值四舍五入到最接近的整数,保留dtype \n", 693 | "modf 将数组的小数和整数部分以两个独立数组的形式返回\n", 694 | "isnan 返回一个表示“哪些值是NaN(这不是一个数字)”的布尔型数组\n", 695 | "isfinite、isinf 分别返回一个表示“哪些元素是有穷的(非inf,非NaN)”或“哪些元素是无穷的”的布尔型数组\n", 696 | "cos、cosh、sin、sinh、tan、tanh 普通型和双曲型三角函数\n", 697 | "arccos、arccosh、arcsin、 反三角函数\n", 698 | "arcsinh、arctan、arctanh logical_not 计算各元素notx的真值。相当于-arr" 699 | ] 700 | }, 701 | { 702 | "cell_type": "code", 703 | "execution_count": 31, 704 | "metadata": {}, 705 | "outputs": [ 706 | { 707 | "name": "stdout", 708 | "output_type": "stream", 709 | "text": [ 710 | "原数组: [ 1. 5.55 123. -0.567 25.532]\n", 711 | "绝对值: [ 1. 5.55 123. 0.567 25.532]\n", 712 | "平方根: [ 1. 2.3558438 11.09053651 nan 5.05291995]\n", 713 | "平方: [1.00000000e+00 3.08025000e+01 1.51290000e+04 3.21489000e-01\n", 714 | " 6.51883024e+02]\n", 715 | "保留一位小数: [ 1. 5.6 123. -0.6 25.5]\n", 716 | "向下取整: [ 1. 5. 123. -1. 25.]\n", 717 | "向上取整: [ 1. 6. 123. -0. 26.]\n" 718 | ] 719 | }, 720 | { 721 | "name": "stderr", 722 | "output_type": "stream", 723 | "text": [ 724 | "D:\\Anaconda3\\lib\\site-packages\\ipykernel_launcher.py:4: RuntimeWarning: invalid value encountered in sqrt\n", 725 | " after removing the cwd from sys.path.\n" 726 | ] 727 | } 728 | ], 729 | "source": [ 730 | "a = np.array([1.0,5.55,123,-0.567,25.532]) \n", 731 | "print ('原数组:',a)\n", 732 | "print('绝对值:',np.abs(a))\n", 733 | "print('平方根:',np.sqrt(a))\n", 734 | "print('平方:',np.square(a))\n", 735 | "print ('保留一位小数:',np.around(a, decimals = 1))\n", 736 | "print ('向下取整:',np.floor(a))\n", 737 | "print ('向上取整:',np.ceil(a))" 738 | ] 739 | }, 740 | { 741 | "cell_type": "code", 742 | "execution_count": 32, 743 | "metadata": {}, 744 | "outputs": [ 745 | { 746 | "name": "stdout", 747 | "output_type": "stream", 748 | "text": [ 749 | "x = [1, 2, 3]\n", 750 | "e^x = [ 2.71828183 7.3890561 20.08553692]\n", 751 | "2^x = [2. 4. 8.]\n", 752 | "3^x = [ 3 9 27]\n", 753 | "ln(x) = [0. 0.69314718 1.09861229]\n", 754 | "log2(x) = [0. 1. 1.5849625]\n", 755 | "log10(x) = [0. 0.30103 0.47712125]\n" 756 | ] 757 | } 758 | ], 759 | "source": [ 760 | "#指数运算\n", 761 | "x = [1, 2, 3]\n", 762 | "print(\"x =\", x)\n", 763 | "print(\"e^x =\", np.exp(x))\n", 764 | "print(\"2^x =\", np.exp2(x))\n", 765 | "print(\"3^x =\", np.power(3, x))\n", 766 | "print(\"ln(x) =\", np.log(x))\n", 767 | "print(\"log2(x) =\", np.log2(x))\n", 768 | "print(\"log10(x) =\", np.log10(x))" 769 | ] 770 | }, 771 | { 772 | "cell_type": "code", 773 | "execution_count": 35, 774 | "metadata": {}, 775 | "outputs": [ 776 | { 777 | "name": "stdout", 778 | "output_type": "stream", 779 | "text": [ 780 | "theta = [0. 1.57079633 3.14159265]\n", 781 | "sin(theta) = [0.0000000e+00 1.0000000e+00 1.2246468e-16]\n", 782 | "cos(theta) = [ 1.000000e+00 6.123234e-17 -1.000000e+00]\n", 783 | "tan(theta) = [ 0.00000000e+00 1.63312394e+16 -1.22464680e-16]\n" 784 | ] 785 | } 786 | ], 787 | "source": [ 788 | "theta = np.linspace(0, np.pi, 3)\n", 789 | "print(\"theta = \", theta)\n", 790 | "print(\"sin(theta) = \", np.sin(theta))\n", 791 | "print(\"cos(theta) = \", np.cos(theta))\n", 792 | "print(\"tan(theta) = \", np.tan(theta))" 793 | ] 794 | }, 795 | { 796 | "cell_type": "code", 797 | "execution_count": 36, 798 | "metadata": {}, 799 | "outputs": [ 800 | { 801 | "name": "stdout", 802 | "output_type": "stream", 803 | "text": [ 804 | "x = [-1, 0, 1]\n", 805 | "arcsin(x) = [-1.57079633 0. 1.57079633]\n", 806 | "arccos(x) = [3.14159265 1.57079633 0. ]\n", 807 | "arctan(x) = [-0.78539816 0. 0.78539816]\n" 808 | ] 809 | } 810 | ], 811 | "source": [ 812 | "x = [-1, 0, 1]\n", 813 | "print(\"x = \", x)\n", 814 | "print(\"arcsin(x) = \", np.arcsin(x))\n", 815 | "print(\"arccos(x) = \", np.arccos(x))\n", 816 | "print(\"arctan(x) = \", np.arctan(x))" 817 | ] 818 | }, 819 | { 820 | "cell_type": "markdown", 821 | "metadata": {}, 822 | "source": [ 823 | "## 二元通用函数" 824 | ] 825 | }, 826 | { 827 | "cell_type": "raw", 828 | "metadata": {}, 829 | "source": [ 830 | "+\tnp.add\t 加法(例如,1 + 1 = 2)\n", 831 | "-\tnp.subtract\t 减法(例如,3 - 2 = 1)\n", 832 | "-\tnp.negative\t 一元否定(例如,-2)\n", 833 | "*\tnp.multiply\t 乘法(例如,2 * 3 = 6)\n", 834 | "/\tnp.divide\t 除法(例如,3 / 2 = 1.5)\n", 835 | "//\tnp.floor_divide\t 取整除法(例如,3 // 2 = 1)\n", 836 | "**\tnp.power\t 指数(例如,2 ** 3 = 8)\n", 837 | "%\tnp.mod\t 模数/余数(例如,9 % 4 = 1)" 838 | ] 839 | }, 840 | { 841 | "cell_type": "code", 842 | "execution_count": 37, 843 | "metadata": {}, 844 | "outputs": [ 845 | { 846 | "name": "stdout", 847 | "output_type": "stream", 848 | "text": [ 849 | "x = [0 1 2 3]\n", 850 | " 算术操作结果 对应Ufunc函数结果\n", 851 | "x + 5 = [5 6 7 8] [5 6 7 8]\n", 852 | "x - 5 = [-5 -4 -3 -2] [-5 -4 -3 -2]\n", 853 | "x * 2 = [0 2 4 6] [0 2 4 6]\n", 854 | "x / 2 = [0. 0.5 1. 1.5] [0. 0.5 1. 1.5]\n", 855 | "x // 2 = [0 0 1 1] [0 0 1 1]\n", 856 | "-x = [ 0 -1 -2 -3] [ 0 -1 -2 -3]\n", 857 | "x ** 2 = [0 1 4 9] [0 1 4 9]\n", 858 | "x % 2 = [0 1 0 1] [0 1 0 1]\n" 859 | ] 860 | } 861 | ], 862 | "source": [ 863 | "x = np.arange(4)\n", 864 | "print(\"x =\", x)\n", 865 | "print(\" 算术操作结果 对应Ufunc函数结果\")\n", 866 | "print(\"x + 5 =\", x + 5,\" \",np.add(x,5))\n", 867 | "print(\"x - 5 =\", x - 5,\" \",np.subtract(x,5))\n", 868 | "print(\"x * 2 =\", x * 2,\" \",np.multiply(x,2))\n", 869 | "print(\"x / 2 =\", x / 2,\" \",np.divide(x,2))\n", 870 | "print(\"x // 2 =\", x // 2,\" \",np.floor_divide(x,2))\n", 871 | "print(\"-x = \", -x,\" \",np.negative(x))\n", 872 | "print(\"x ** 2 = \", x ** 2,\" \",np.power(x,2))\n", 873 | "print(\"x % 2 = \", x % 2,\" \",np.mod(x,2))" 874 | ] 875 | }, 876 | { 877 | "cell_type": "markdown", 878 | "metadata": {}, 879 | "source": [ 880 | "## 执行特定矢量化运算的特殊ufunc方法" 881 | ] 882 | }, 883 | { 884 | "cell_type": "raw", 885 | "metadata": {}, 886 | "source": [ 887 | "NumPy的各个二元ufunc都有一些用于执行特定矢量化运算的特殊方法。\n", 888 | "reduce(x)reduce接受一个数组参数,并通过一系列的二元运算对其值进行聚合(可指明轴向)\n", 889 | "accumulate(x)聚合值,保留所有局部聚合结果\n", 890 | "outer(x,y)对x和y中的每对元素应用原始运算。结果数组的形状为x.shape+y.shape\n", 891 | "reduceat(x,bins)“局部”约简(也就是groupby)。约简数据的各个切片以产生聚合型数组" 892 | ] 893 | }, 894 | { 895 | "cell_type": "code", 896 | "execution_count": 38, 897 | "metadata": {}, 898 | "outputs": [ 899 | { 900 | "data": { 901 | "text/plain": [ 902 | "(45, 45)" 903 | ] 904 | }, 905 | "execution_count": 38, 906 | "metadata": {}, 907 | "output_type": "execute_result" 908 | } 909 | ], 910 | "source": [ 911 | "#我们可以用np.add.reduce对数组中各个元素进行求和。\n", 912 | "#起始值取决于ufunc(对于add的情况,就是0)。如果设置了轴号,约简运算就会沿该轴向执行。\n", 913 | "arr=np. arange(10)\n", 914 | "np.add.reduce(arr),arr.sum()" 915 | ] 916 | }, 917 | { 918 | "cell_type": "code", 919 | "execution_count": 42, 920 | "metadata": {}, 921 | "outputs": [ 922 | { 923 | "data": { 924 | "text/plain": [ 925 | "(array([[ True, True, True, True],\n", 926 | " [False, True, True, False],\n", 927 | " [ True, True, True, True],\n", 928 | " [ True, False, True, False],\n", 929 | " [ True, True, True, True]]),\n", 930 | " array([ True, False, True, False, True]))" 931 | ] 932 | }, 933 | "execution_count": 42, 934 | "metadata": {}, 935 | "output_type": "execute_result" 936 | } 937 | ], 938 | "source": [ 939 | "#用np.1ogical_and检查数组各行中的值是否是有序的:\n", 940 | "arr=np.random.randn(5,5)\n", 941 | "arr[::2].sort(1)#对部分行进行排序\n", 942 | "arr[:,:-1]\u001b[0m in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[0;32m 8\u001b[0m \u001b[0mprint\u001b[0m \u001b[1;33m(\u001b[0m\u001b[1;34m\"行列式:\\n\"\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0mnp\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mlinalg\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mdet\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0ma\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 9\u001b[0m \u001b[0mprint\u001b[0m \u001b[1;33m(\u001b[0m\u001b[1;34m'a 的逆:\\n'\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0mnp\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mlinalg\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0minv\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0ma\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 10\u001b[1;33m \u001b[0mprint\u001b[0m \u001b[1;33m(\u001b[0m\u001b[1;34m'a 的对角线和:\\n'\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0mnp\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mlinalg\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mtrace\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0ma\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 11\u001b[0m \u001b[0mprint\u001b[0m \u001b[1;33m(\u001b[0m\u001b[1;34m'a 的本征值和本征向量:\\n'\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0mnp\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mlinalg\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0meig\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0ma\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 12\u001b[0m \u001b[0mprint\u001b[0m \u001b[1;33m(\u001b[0m\u001b[1;34m'a 的伪逆矩阵:\\n'\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0mnp\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mlinalg\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mpinv\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0ma\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", 1548 | "\u001b[1;31mAttributeError\u001b[0m: module 'numpy.linalg' has no attribute 'trace'" 1549 | ] 1550 | } 1551 | ], 1552 | "source": [ 1553 | "a = np.array([[1,2],[3,4]])\n", 1554 | "b = np.array([[11,12],[13,14]])\n", 1555 | "print(\"a:\\n\",a)\n", 1556 | "print(\"b:\\n\",b)\n", 1557 | "print (\"点积:\\n\",np.dot(a,b))\n", 1558 | "print (\"内积:\\n\",np.inner(a,b))\n", 1559 | "print (\"矩阵积:\\n\",np.matmul(a,b))\n", 1560 | "print (\"行列式:\\n\",np.linalg.det(a))\n", 1561 | "print ('a 的逆:\\n',np.linalg.inv(a) )\n", 1562 | "print ('a 的对角线和:\\n',np.linalg.trace(a))\n", 1563 | "print ('a 的本征值和本征向量:\\n',np.linalg.eig(a))\n", 1564 | "print ('a 的伪逆矩阵:\\n',np.linalg.pinv(a))" 1565 | ] 1566 | }, 1567 | { 1568 | "cell_type": "code", 1569 | "execution_count": 75, 1570 | "metadata": {}, 1571 | "outputs": [ 1572 | { 1573 | "name": "stdout", 1574 | "output_type": "stream", 1575 | "text": [ 1576 | "计算:A^(-1)B:\n", 1577 | "[[ 5.]\n", 1578 | " [ 3.]\n", 1579 | " [-2.]]\n" 1580 | ] 1581 | } 1582 | ], 1583 | "source": [ 1584 | "#slove\n", 1585 | "a = np.array([[1,1,1],[0,2,5],[2,5,-1]]) \n", 1586 | "b = np.array([[6],[-4],[27]]) \n", 1587 | "print ('计算:A^(-1)B:')\n", 1588 | "x = np.linalg.solve(a,b) \n", 1589 | "print (x)" 1590 | ] 1591 | }, 1592 | { 1593 | "cell_type": "code", 1594 | "execution_count": 76, 1595 | "metadata": {}, 1596 | "outputs": [ 1597 | { 1598 | "name": "stdout", 1599 | "output_type": "stream", 1600 | "text": [ 1601 | "[[ 6 24 16 22 17]\n", 1602 | " [20 14 11 14 15]\n", 1603 | " [ 5 9 3 14 9]\n", 1604 | " [ 9 2 16 3 16]\n", 1605 | " [24 21 20 7 8]]\n" 1606 | ] 1607 | } 1608 | ], 1609 | "source": [ 1610 | "#svd\n", 1611 | "S = np.zeros([5,5])\n", 1612 | "A=np.random.randint(1,25,[5,5])\n", 1613 | "u,sigma,vt = np.linalg.svd(A)\n", 1614 | "print(A)" 1615 | ] 1616 | }, 1617 | { 1618 | "cell_type": "code", 1619 | "execution_count": 77, 1620 | "metadata": {}, 1621 | "outputs": [ 1622 | { 1623 | "name": "stderr", 1624 | "output_type": "stream", 1625 | "text": [ 1626 | "D:\\Anaconda3\\lib\\site-packages\\ipykernel_launcher.py:9: FutureWarning: `rcond` parameter will change to the default of machine precision times ``max(M, N)`` where M and N are the input matrix dimensions.\n", 1627 | "To use the future default and silence this warning we advise to pass `rcond=None`, to keep using the old, explicitly pass `rcond=-1`.\n", 1628 | " if __name__ == '__main__':\n" 1629 | ] 1630 | } 1631 | ], 1632 | "source": [ 1633 | "#lstsq,传入A.T和观测值里的变量即可求得f(x)=a+bx里的a和b。a和b记录在lstsq函数的第一个返回值里\n", 1634 | "#第一个返回值sol共有两个值,sol[0]即是估计出来的f(x)=a+bx里a,sol[1]代表f(x)=a+bx里b。因此f(x)为:y_fit = sol[0] + sol[1] * x\n", 1635 | "m = 100\n", 1636 | "x = np.linspace(-1, 1, m)\n", 1637 | "y_exact = 1 + 2 * x\n", 1638 | "xi = x + np.random.normal(0, 0.05, 100)\n", 1639 | "yi = 1 + 2 * xi + np.random.normal(0, 0.05, 100)\n", 1640 | "A = np.vstack([xi**0, xi**1])\n", 1641 | "sol, r, rank, s = np.linalg.lstsq(A.T, yi) #求取各个系数大小\n", 1642 | "y_fit = sol[0] + sol[1] * x" 1643 | ] 1644 | }, 1645 | { 1646 | "cell_type": "markdown", 1647 | "metadata": {}, 1648 | "source": [ 1649 | "# 八、高级数组操作\n", 1650 | "除花式索引、切片、布尔条件取子集等操作之外,数组的操作方式还有很多。虽然pandas中的高级函数可以处理数据分析工作中的许多重型任务,但有时你还是需要编写一些在现有库中找不到的数据算法。本部分主要介绍转置数组、数组重塑、合并与拆分。" 1651 | ] 1652 | }, 1653 | { 1654 | "cell_type": "markdown", 1655 | "metadata": {}, 1656 | "source": [ 1657 | "## 翻转、转置数组" 1658 | ] 1659 | }, 1660 | { 1661 | "cell_type": "raw", 1662 | "metadata": {}, 1663 | "source": [ 1664 | "numpy.transpose(arr, axes)对换数组的维度,如形状 (2,3,4) transpose 后就变成 (4,3,2)。\n", 1665 | "ndarray.T 和transpose() 相同" 1666 | ] 1667 | }, 1668 | { 1669 | "cell_type": "code", 1670 | "execution_count": 78, 1671 | "metadata": {}, 1672 | "outputs": [ 1673 | { 1674 | "data": { 1675 | "text/plain": [ 1676 | "(array([[1, 3],\n", 1677 | " [2, 4]]), array([[1, 3],\n", 1678 | " [2, 4]]))" 1679 | ] 1680 | }, 1681 | "execution_count": 78, 1682 | "metadata": {}, 1683 | "output_type": "execute_result" 1684 | } 1685 | ], 1686 | "source": [ 1687 | "# transpose,T\n", 1688 | "a = np.array([[1,2],[3,4]])\n", 1689 | "np.transpose(a),a.T" 1690 | ] 1691 | }, 1692 | { 1693 | "cell_type": "markdown", 1694 | "metadata": {}, 1695 | "source": [ 1696 | "## 数组重塑\n", 1697 | "鉴于我们已经学过的有关NumPy数组的知识,当你知道“无需复制任何数据,数组就能从一个形状转换为另一个形状”时应该会感到有一点吃惊。只需向数组的实例方法reshape传入一个表示新形状的元组即可实现该目的。假设有一个一维数组,我们希望将其重新排列为一个矩阵:" 1698 | ] 1699 | }, 1700 | { 1701 | "cell_type": "code", 1702 | "execution_count": 79, 1703 | "metadata": {}, 1704 | "outputs": [ 1705 | { 1706 | "data": { 1707 | "text/plain": [ 1708 | "(array([0, 1, 2, 3, 4, 5, 6, 7]), array([[0, 1],\n", 1709 | " [2, 3],\n", 1710 | " [4, 5],\n", 1711 | " [6, 7]]))" 1712 | ] 1713 | }, 1714 | "execution_count": 79, 1715 | "metadata": {}, 1716 | "output_type": "execute_result" 1717 | } 1718 | ], 1719 | "source": [ 1720 | "#numpy.reshape(arr, newshape, order='C') 不改变数据的条件下修改形状\n", 1721 | "a = np.arange(8)\n", 1722 | "b = a.reshape(4,2)\n", 1723 | "a,b" 1724 | ] 1725 | }, 1726 | { 1727 | "cell_type": "code", 1728 | "execution_count": 80, 1729 | "metadata": {}, 1730 | "outputs": [ 1731 | { 1732 | "data": { 1733 | "text/plain": [ 1734 | "(array([[ 0, 1, 2],\n", 1735 | " [ 3, 4, 5],\n", 1736 | " [ 6, 7, 8],\n", 1737 | " [ 9, 10, 11],\n", 1738 | " [12, 13, 14]]),\n", 1739 | " array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]))" 1740 | ] 1741 | }, 1742 | "execution_count": 80, 1743 | "metadata": {}, 1744 | "output_type": "execute_result" 1745 | } 1746 | ], 1747 | "source": [ 1748 | "#与reshape将一维数组转换为多维数组的运算过程相反的运算通常称为扁平化(flattening)或散开(raveling):\n", 1749 | "arr=np. arange(15). reshape((5,3))\n", 1750 | "arr,arr.ravel()" 1751 | ] 1752 | }, 1753 | { 1754 | "cell_type": "code", 1755 | "execution_count": 82, 1756 | "metadata": {}, 1757 | "outputs": [ 1758 | { 1759 | "data": { 1760 | "text/plain": [ 1761 | "array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14])" 1762 | ] 1763 | }, 1764 | "execution_count": 82, 1765 | "metadata": {}, 1766 | "output_type": "execute_result" 1767 | } 1768 | ], 1769 | "source": [ 1770 | "#如果没有必要,rave1不会产生源数据的副本(下面将详细介绍)。flatten方法的行为类似于rave1,只不过它总是返回数据的副本:\n", 1771 | "arr.flatten()" 1772 | ] 1773 | }, 1774 | { 1775 | "cell_type": "markdown", 1776 | "metadata": {}, 1777 | "source": [ 1778 | "## 数组的合并和拆分" 1779 | ] 1780 | }, 1781 | { 1782 | "cell_type": "raw", 1783 | "metadata": {}, 1784 | "source": [ 1785 | "numpy.concatenate((a1, a2, ...), axis)沿指定轴axis连接相同形状的两个或多个数组\n", 1786 | "numpy.stack(arrays, axis) 沿新轴axis连接数组序列\n", 1787 | " 便捷化函数:vstack、hstack、dstack以(沿轴0)(沿轴1)(沿轴2)的方式对数组进行堆叠\n", 1788 | "numpy.split(ary, indices_or_sections, axis)将一个数组ary分割为indices_or_sections个子数组,axis是沿着哪个维度进行切向,默认为0,横向切分。为1时,纵向切分\n", 1789 | " 便捷化函数:hsplit、vsplit、dsplit split分别沿轴0、轴1、轴2进行拆分" 1790 | ] 1791 | }, 1792 | { 1793 | "cell_type": "code", 1794 | "execution_count": 83, 1795 | "metadata": {}, 1796 | "outputs": [ 1797 | { 1798 | "name": "stdout", 1799 | "output_type": "stream", 1800 | "text": [ 1801 | "第一个数组:\n", 1802 | "[[1 2]\n", 1803 | " [3 4]]\n", 1804 | "第二个数组:\n", 1805 | "[[5 6]\n", 1806 | " [7 8]]\n", 1807 | "沿轴 0 连接两个数组:\n", 1808 | "[[1 2]\n", 1809 | " [3 4]\n", 1810 | " [5 6]\n", 1811 | " [7 8]]\n", 1812 | "沿轴 1 连接两个数组:\n", 1813 | "[[1 2 5 6]\n", 1814 | " [3 4 7 8]]\n" 1815 | ] 1816 | } 1817 | ], 1818 | "source": [ 1819 | "#concatenate\n", 1820 | "a = np.array([[1,2],[3,4]])\n", 1821 | "print ('第一个数组:')\n", 1822 | "print (a)\n", 1823 | "\n", 1824 | "b = np.array([[5,6],[7,8]])\n", 1825 | "print ('第二个数组:')\n", 1826 | "print (b)\n", 1827 | "\n", 1828 | "# 两个数组的维度相同\n", 1829 | "print ('沿轴 0 连接两个数组:')\n", 1830 | "print (np.concatenate((a,b)))\n", 1831 | "print ('沿轴 1 连接两个数组:')\n", 1832 | "print (np.concatenate((a,b),axis = 1))" 1833 | ] 1834 | }, 1835 | { 1836 | "cell_type": "code", 1837 | "execution_count": 84, 1838 | "metadata": {}, 1839 | "outputs": [ 1840 | { 1841 | "name": "stdout", 1842 | "output_type": "stream", 1843 | "text": [ 1844 | "第一个数组:\n", 1845 | "[[1 2]\n", 1846 | " [3 4]]\n", 1847 | "第二个数组:\n", 1848 | "[[5 6]\n", 1849 | " [7 8]]\n", 1850 | "沿轴 0 堆叠两个数组:\n", 1851 | "[[[1 2]\n", 1852 | " [3 4]]\n", 1853 | "\n", 1854 | " [[5 6]\n", 1855 | " [7 8]]]\n", 1856 | "沿轴 1 堆叠两个数组:\n", 1857 | "[[[1 2]\n", 1858 | " [5 6]]\n", 1859 | "\n", 1860 | " [[3 4]\n", 1861 | " [7 8]]]\n" 1862 | ] 1863 | } 1864 | ], 1865 | "source": [ 1866 | "#stack\n", 1867 | "a = np.array([[1,2],[3,4]])\n", 1868 | " \n", 1869 | "print ('第一个数组:')\n", 1870 | "print (a)\n", 1871 | "\n", 1872 | "b = np.array([[5,6],[7,8]])\n", 1873 | "print ('第二个数组:')\n", 1874 | "print (b)\n", 1875 | "\n", 1876 | "print ('沿轴 0 堆叠两个数组:')\n", 1877 | "print (np.stack((a,b),0))\n", 1878 | "print ('沿轴 1 堆叠两个数组:')\n", 1879 | "print (np.stack((a,b),1))" 1880 | ] 1881 | }, 1882 | { 1883 | "cell_type": "code", 1884 | "execution_count": 85, 1885 | "metadata": {}, 1886 | "outputs": [ 1887 | { 1888 | "name": "stdout", 1889 | "output_type": "stream", 1890 | "text": [ 1891 | "第一个数组:\n", 1892 | "[0 1 2 3 4 5 6 7 8]\n", 1893 | "将数组分为三个大小相等的子数组:\n", 1894 | "[array([0, 1, 2]), array([3, 4, 5]), array([6, 7, 8])]\n", 1895 | "将数组在一维数组中表明的位置分割:\n", 1896 | "[array([0, 1, 2, 3]), array([4, 5, 6]), array([7, 8])]\n" 1897 | ] 1898 | } 1899 | ], 1900 | "source": [ 1901 | "#split\n", 1902 | "a = np.arange(9)\n", 1903 | "print ('第一个数组:')\n", 1904 | "print (a)\n", 1905 | " \n", 1906 | "print ('将数组分为三个大小相等的子数组:')\n", 1907 | "b = np.split(a,3)\n", 1908 | "print (b)\n", 1909 | "\n", 1910 | "print ('将数组在一维数组中表明的位置分割:')\n", 1911 | "b = np.split(a,[4,7])\n", 1912 | "print (b)" 1913 | ] 1914 | }, 1915 | { 1916 | "cell_type": "markdown", 1917 | "metadata": {}, 1918 | "source": [ 1919 | "## 数组元素的添加与删除" 1920 | ] 1921 | }, 1922 | { 1923 | "cell_type": "raw", 1924 | "metadata": {}, 1925 | "source": [ 1926 | "numpy.append(arr, values, axis=None)在数组的末尾添加值。 追加操作会分配整个数组,并把原来的数组复制到新数组中。\n", 1927 | "numpy.insert(arr, obj, values, axis)在给定索引obj之前,沿给定轴axis在输入数组arr中插入值values\n", 1928 | "numpy.delete(arr, obj, axis)从输入数组arr中删除指定子数组的新数组" 1929 | ] 1930 | }, 1931 | { 1932 | "cell_type": "code", 1933 | "execution_count": 86, 1934 | "metadata": {}, 1935 | "outputs": [ 1936 | { 1937 | "name": "stdout", 1938 | "output_type": "stream", 1939 | "text": [ 1940 | "第一个数组:\n", 1941 | "[[1 2 3]\n", 1942 | " [4 5 6]]\n", 1943 | "向数组添加元素:\n", 1944 | "[1 2 3 4 5 6 7 8 9]\n" 1945 | ] 1946 | } 1947 | ], 1948 | "source": [ 1949 | "#append\n", 1950 | "a = np.array([[1,2,3],[4,5,6]])\n", 1951 | "print ('第一个数组:')\n", 1952 | "print (a)\n", 1953 | "print ('向数组添加元素:')\n", 1954 | "print (np.append(a, [7,8,9]))" 1955 | ] 1956 | }, 1957 | { 1958 | "cell_type": "code", 1959 | "execution_count": 87, 1960 | "metadata": {}, 1961 | "outputs": [ 1962 | { 1963 | "name": "stdout", 1964 | "output_type": "stream", 1965 | "text": [ 1966 | "[[1 2]\n", 1967 | " [3 4]\n", 1968 | " [5 6]]\n", 1969 | "[ 1 2 3 11 12 4 5 6]\n", 1970 | "[[ 1 2]\n", 1971 | " [11 11]\n", 1972 | " [ 3 4]\n", 1973 | " [ 5 6]]\n" 1974 | ] 1975 | } 1976 | ], 1977 | "source": [ 1978 | "#insert\n", 1979 | "a = np.array([[1,2],[3,4],[5,6]])\n", 1980 | "print (a)\n", 1981 | "print (np.insert(a,3,[11,12]))\n", 1982 | "print (np.insert(a,1,[11],axis = 0))" 1983 | ] 1984 | }, 1985 | { 1986 | "cell_type": "code", 1987 | "execution_count": 88, 1988 | "metadata": {}, 1989 | "outputs": [ 1990 | { 1991 | "name": "stdout", 1992 | "output_type": "stream", 1993 | "text": [ 1994 | "[[ 0 1 2 3]\n", 1995 | " [ 4 5 6 7]\n", 1996 | " [ 8 9 10 11]]\n", 1997 | "[ 0 1 3 4 5 6 7 8 9 10 11]\n", 1998 | "[[ 0 1 3]\n", 1999 | " [ 4 5 7]\n", 2000 | " [ 8 9 11]]\n" 2001 | ] 2002 | } 2003 | ], 2004 | "source": [ 2005 | "#delete\n", 2006 | "a = np.arange(12).reshape(3,4)\n", 2007 | "print (a)\n", 2008 | "print (np.delete(a,2))#删除展开后的第2列\n", 2009 | "print (np.delete(a,2,axis = 1))#删除第二列" 2010 | ] 2011 | }, 2012 | { 2013 | "cell_type": "markdown", 2014 | "metadata": {}, 2015 | "source": [ 2016 | "# 九、广播" 2017 | ] 2018 | }, 2019 | { 2020 | "cell_type": "raw", 2021 | "metadata": {}, 2022 | "source": [ 2023 | "广播(Broadcast)是 numpy 很重要的一个特性,它对不同形状(shape)的数组进行数值计算的方式, 通常在数组的算术运算对相应的元素进行。\n", 2024 | "如果两个数组 a 和 b 形状相同,即满足 a.shape == b.shape,那么 a*b 的结果就是 a 与 b 数组对应位相乘。这要求维数相同,且各维度的长度相同。\n", 2025 | "NumPy中的广播遵循一组严格的规则来确定两个数组之间的相互作用\n", 2026 | "规则1:如果这两个数组的维数不同,则维数较少的数组的形状为衬垫在它的前面(左边)。\n", 2027 | "规则2:如果两个数组的形状在任何维度中不匹配,则在该维度中形状等于1的数组将被拉伸以与另一个形状匹配。\n", 2028 | "规则3:如果在任何维度中,大小不一致,且两者都不等于1,则会引发错误。" 2029 | ] 2030 | }, 2031 | { 2032 | "cell_type": "code", 2033 | "execution_count": 89, 2034 | "metadata": {}, 2035 | "outputs": [ 2036 | { 2037 | "data": { 2038 | "text/plain": [ 2039 | "array([5, 6, 7])" 2040 | ] 2041 | }, 2042 | "execution_count": 89, 2043 | "metadata": {}, 2044 | "output_type": "execute_result" 2045 | } 2046 | ], 2047 | "source": [ 2048 | "#对于相同大小的数组,在逐个元素的基础上执行:\n", 2049 | "a = np.array([0, 1, 2])\n", 2050 | "b = np.array([5, 5, 5])\n", 2051 | "a + b" 2052 | ] 2053 | }, 2054 | { 2055 | "cell_type": "code", 2056 | "execution_count": 90, 2057 | "metadata": {}, 2058 | "outputs": [ 2059 | { 2060 | "data": { 2061 | "text/plain": [ 2062 | "array([5, 6, 7])" 2063 | ] 2064 | }, 2065 | "execution_count": 90, 2066 | "metadata": {}, 2067 | "output_type": "execute_result" 2068 | } 2069 | ], 2070 | "source": [ 2071 | "#广播允许在不同大小的数组上执行这些类型操作\n", 2072 | "#例如,我们可以很容易地将标量(将其视为零维数组)添加到数组中:\n", 2073 | "a + 5" 2074 | ] 2075 | }, 2076 | { 2077 | "cell_type": "raw", 2078 | "metadata": {}, 2079 | "source": [ 2080 | "5进入数组[5, 5, 5],并加结果到a。\n", 2081 | "我们也可以将其扩展到更高维度的数组。" 2082 | ] 2083 | }, 2084 | { 2085 | "cell_type": "code", 2086 | "execution_count": 91, 2087 | "metadata": {}, 2088 | "outputs": [ 2089 | { 2090 | "data": { 2091 | "text/plain": [ 2092 | "array([[1., 1., 1.],\n", 2093 | " [1., 1., 1.],\n", 2094 | " [1., 1., 1.]])" 2095 | ] 2096 | }, 2097 | "execution_count": 91, 2098 | "metadata": {}, 2099 | "output_type": "execute_result" 2100 | } 2101 | ], 2102 | "source": [ 2103 | "# 在将一维数组添加到二维数组时\n", 2104 | "M = np.ones((3, 3))\n", 2105 | "M" 2106 | ] 2107 | }, 2108 | { 2109 | "cell_type": "code", 2110 | "execution_count": 92, 2111 | "metadata": {}, 2112 | "outputs": [ 2113 | { 2114 | "data": { 2115 | "text/plain": [ 2116 | "array([[1., 2., 3.],\n", 2117 | " [1., 2., 3.],\n", 2118 | " [1., 2., 3.]])" 2119 | ] 2120 | }, 2121 | "execution_count": 92, 2122 | "metadata": {}, 2123 | "output_type": "execute_result" 2124 | } 2125 | ], 2126 | "source": [ 2127 | "M + a" 2128 | ] 2129 | }, 2130 | { 2131 | "cell_type": "raw", 2132 | "metadata": {}, 2133 | "source": [ 2134 | "虽然这些例子相对容易理解,但更复杂的例子可能涉及两个数组的广播。" 2135 | ] 2136 | }, 2137 | { 2138 | "cell_type": "code", 2139 | "execution_count": 93, 2140 | "metadata": {}, 2141 | "outputs": [ 2142 | { 2143 | "name": "stdout", 2144 | "output_type": "stream", 2145 | "text": [ 2146 | "[0 1 2]\n", 2147 | "[[0]\n", 2148 | " [1]\n", 2149 | " [2]]\n" 2150 | ] 2151 | } 2152 | ], 2153 | "source": [ 2154 | "a = np.arange(3)\n", 2155 | "b = np.arange(3)[:, np.newaxis]\n", 2156 | "print(a)\n", 2157 | "print(b)" 2158 | ] 2159 | }, 2160 | { 2161 | "cell_type": "code", 2162 | "execution_count": 94, 2163 | "metadata": {}, 2164 | "outputs": [ 2165 | { 2166 | "data": { 2167 | "text/plain": [ 2168 | "array([[0, 1, 2],\n", 2169 | " [1, 2, 3],\n", 2170 | " [2, 3, 4]])" 2171 | ] 2172 | }, 2173 | "execution_count": 94, 2174 | "metadata": {}, 2175 | "output_type": "execute_result" 2176 | } 2177 | ], 2178 | "source": [ 2179 | "a + b" 2180 | ] 2181 | }, 2182 | { 2183 | "cell_type": "markdown", 2184 | "metadata": {}, 2185 | "source": [ 2186 | "## 广播实例与分析过程" 2187 | ] 2188 | }, 2189 | { 2190 | "cell_type": "code", 2191 | "execution_count": 95, 2192 | "metadata": { 2193 | "collapsed": true 2194 | }, 2195 | "outputs": [], 2196 | "source": [ 2197 | "#向一维数组中添加一个二维数组\n", 2198 | "M = np.ones((2, 3))\n", 2199 | "a = np.arange(3)\n", 2200 | "#两个数组都需要广播的例子\n", 2201 | "c = np.arange(3).reshape((3, 1))\n", 2202 | "d = np.arange(3)" 2203 | ] 2204 | }, 2205 | { 2206 | "cell_type": "raw", 2207 | "metadata": {}, 2208 | "source": [ 2209 | "思考:\n", 2210 | "数组的形状如下\n", 2211 | "M.shape = (2, 3)\n", 2212 | "a.shape = (3,)\n", 2213 | "c.shape = (3, 1)\n", 2214 | "d.shape = (3,)\n", 2215 | "\n", 2216 | "我们通过规则1看到数组a,d维度较少,所以我们把1放在左边:\n", 2217 | "M.shape -> (2, 3)\n", 2218 | "a.shape -> (1, 3)\n", 2219 | "c.shape -> (3, 1)\n", 2220 | "d.shape -> (1, 3)\n", 2221 | "\n", 2222 | "根据规则2,我们现在看到第一个维度不一致,因此我们扩展这个维度来匹配:\n", 2223 | "M.shape -> (2, 3)\n", 2224 | "a.shape -> (2, 3)\n", 2225 | "c.shape -> (3, 3)\n", 2226 | "d.shape -> (3, 3)" 2227 | ] 2228 | }, 2229 | { 2230 | "cell_type": "code", 2231 | "execution_count": 96, 2232 | "metadata": {}, 2233 | "outputs": [ 2234 | { 2235 | "data": { 2236 | "text/plain": [ 2237 | "array([[1., 2., 3.],\n", 2238 | " [1., 2., 3.]])" 2239 | ] 2240 | }, 2241 | "execution_count": 96, 2242 | "metadata": {}, 2243 | "output_type": "execute_result" 2244 | } 2245 | ], 2246 | "source": [ 2247 | "#[[1. 1. 1.] + [0 1 2]\n", 2248 | "# [1. 1. 1.]]\n", 2249 | "M + a" 2250 | ] 2251 | }, 2252 | { 2253 | "cell_type": "code", 2254 | "execution_count": 97, 2255 | "metadata": {}, 2256 | "outputs": [ 2257 | { 2258 | "data": { 2259 | "text/plain": [ 2260 | "array([[0, 1, 2],\n", 2261 | " [1, 2, 3],\n", 2262 | " [2, 3, 4]])" 2263 | ] 2264 | }, 2265 | "execution_count": 97, 2266 | "metadata": {}, 2267 | "output_type": "execute_result" 2268 | } 2269 | ], 2270 | "source": [ 2271 | "#[[0]\n", 2272 | "# [1] + [0 1 2]\n", 2273 | "# [2]] \n", 2274 | "c+d" 2275 | ] 2276 | }, 2277 | { 2278 | "cell_type": "code", 2279 | "execution_count": 98, 2280 | "metadata": {}, 2281 | "outputs": [ 2282 | { 2283 | "data": { 2284 | "text/plain": [ 2285 | "(array([[1., 1.],\n", 2286 | " [1., 1.],\n", 2287 | " [1., 1.]]), array([0, 1, 2]))" 2288 | ] 2289 | }, 2290 | "execution_count": 98, 2291 | "metadata": {}, 2292 | "output_type": "execute_result" 2293 | } 2294 | ], 2295 | "source": [ 2296 | "#形状不匹配的情况下又是如何呢?\n", 2297 | "M = np.ones((3, 2))\n", 2298 | "a = np.arange(3)\n", 2299 | "M,a" 2300 | ] 2301 | }, 2302 | { 2303 | "cell_type": "raw", 2304 | "metadata": {}, 2305 | "source": [ 2306 | "同样,我们将从写出数组的形状开始:\n", 2307 | "\n", 2308 | "M.shape = (3, 2)\n", 2309 | "a.shape = (3,)\n", 2310 | "\n", 2311 | "M.shape -> (3, 2)\n", 2312 | "a.shape -> (1, 3)\n", 2313 | "\n", 2314 | "M.shape -> (3, 2)\n", 2315 | "a.shape -> (3, 3)\n", 2316 | "最终的形状不匹配,所以这两个数组是不兼容的,无法计算出结果" 2317 | ] 2318 | }, 2319 | { 2320 | "cell_type": "code", 2321 | "execution_count": 99, 2322 | "metadata": {}, 2323 | "outputs": [ 2324 | { 2325 | "ename": "ValueError", 2326 | "evalue": "operands could not be broadcast together with shapes (3,2) (3,) ", 2327 | "output_type": "error", 2328 | "traceback": [ 2329 | "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", 2330 | "\u001b[1;31mValueError\u001b[0m Traceback (most recent call last)", 2331 | "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[0;32m 2\u001b[0m \u001b[1;31m#[1, 1], + [0, 1, 2]\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 3\u001b[0m \u001b[1;31m#[1, 1]]\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 4\u001b[1;33m \u001b[0mM\u001b[0m \u001b[1;33m+\u001b[0m \u001b[0ma\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", 2332 | "\u001b[1;31mValueError\u001b[0m: operands could not be broadcast together with shapes (3,2) (3,) " 2333 | ] 2334 | } 2335 | ], 2336 | "source": [ 2337 | "#[[1, 1],\n", 2338 | "#[1, 1], + [0, 1, 2]\n", 2339 | "#[1, 1]]\n", 2340 | "M + a" 2341 | ] 2342 | }, 2343 | { 2344 | "cell_type": "code", 2345 | "execution_count": 100, 2346 | "metadata": {}, 2347 | "outputs": [ 2348 | { 2349 | "data": { 2350 | "text/plain": [ 2351 | "array([[1., 1.],\n", 2352 | " [2., 2.],\n", 2353 | " [3., 3.]])" 2354 | ] 2355 | }, 2356 | "execution_count": 100, 2357 | "metadata": {}, 2358 | "output_type": "execute_result" 2359 | } 2360 | ], 2361 | "source": [ 2362 | "#解决:还记得newaxis吗?\n", 2363 | "M + a[:, np.newaxis]" 2364 | ] 2365 | }, 2366 | { 2367 | "cell_type": "code", 2368 | "execution_count": null, 2369 | "metadata": { 2370 | "collapsed": true 2371 | }, 2372 | "outputs": [], 2373 | "source": [] 2374 | } 2375 | ], 2376 | "metadata": { 2377 | "kernelspec": { 2378 | "display_name": "Python 3", 2379 | "language": "python", 2380 | "name": "python3" 2381 | }, 2382 | "language_info": { 2383 | "codemirror_mode": { 2384 | "name": "ipython", 2385 | "version": 3 2386 | }, 2387 | "file_extension": ".py", 2388 | "mimetype": "text/x-python", 2389 | "name": "python", 2390 | "nbconvert_exporter": "python", 2391 | "pygments_lexer": "ipython3", 2392 | "version": "3.6.1" 2393 | }, 2394 | "varInspector": { 2395 | "cols": { 2396 | "lenName": 16, 2397 | "lenType": 16, 2398 | "lenVar": 40 2399 | }, 2400 | "kernels_config": { 2401 | "python": { 2402 | "delete_cmd_postfix": "", 2403 | "delete_cmd_prefix": "del ", 2404 | "library": "var_list.py", 2405 | "varRefreshCmd": "print(var_dic_list())" 2406 | }, 2407 | "r": { 2408 | "delete_cmd_postfix": ") ", 2409 | "delete_cmd_prefix": "rm(", 2410 | "library": "var_list.r", 2411 | "varRefreshCmd": "cat(var_dic_list()) " 2412 | } 2413 | }, 2414 | "types_to_exclude": [ 2415 | "module", 2416 | "function", 2417 | "builtin_function_or_method", 2418 | "instance", 2419 | "_Feature" 2420 | ], 2421 | "window_display": false 2422 | } 2423 | }, 2424 | "nbformat": 4, 2425 | "nbformat_minor": 2 2426 | } 2427 | -------------------------------------------------------------------------------- /3 Numpy计算.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetalkdata/python_script-manual/4720aec496fe9b6f2b5e5fa92cf6aace864aac82/3 Numpy计算.pdf -------------------------------------------------------------------------------- /4 文件读取与文件合并.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetalkdata/python_script-manual/4720aec496fe9b6f2b5e5fa92cf6aace864aac82/4 文件读取与文件合并.pdf -------------------------------------------------------------------------------- /5 python 正则表达式.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetalkdata/python_script-manual/4720aec496fe9b6f2b5e5fa92cf6aace864aac82/5 python 正则表达式.pdf -------------------------------------------------------------------------------- /6 日期、时序函数的生成与转化.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetalkdata/python_script-manual/4720aec496fe9b6f2b5e5fa92cf6aace864aac82/6 日期、时序函数的生成与转化.pdf -------------------------------------------------------------------------------- /7 Python 类与对象.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "source": [ 6 | "# 第7章 python类与对象\n", 7 | "在Python中,所有数据类型都可以视为对象。面向对象的程序设计把计算机程序视为一组对象的集合,而每个对象都可以接收其他对象发过来的消息,并处理这些消息,计算机程序的执行就是一系列消息在各个对象之间传递。下面是面向对象编程(OOP)的一个名称介绍:\n", 8 | "- 类:用于定义表示用户定义对象的一组属性的原型。属性是通过点符号访问的数据成员(类变量和实例变量)和方法。\n", 9 | "- 类变量:由类的所有实例共享的变量。类变量在类中定义,但在类的任何方法之外。类变量不像实例变量那样频繁使用。\n", 10 | "- 数据成员:保存和类及其对象相关联的数据的类变量或实例变量。\n", 11 | "- 函数重载:将多个行为分配给特定函数。执行的操作因涉及的对象或参数的类型而异。\n", 12 | "- 实例变量:在方法中定义并仅属于类的当前实例的变量。\n", 13 | "- 继承:将类的特征传递给从其派生的其他类。\n", 14 | "- 实例:某个类的单个对象。\n", 15 | "- 实例化:创建类的实例。\n", 16 | "- 方法:在类定义中定义的一种特殊类型的函数。\n", 17 | "- 对象:由其类定义的数据结构的唯一实例。对象包括数据成员(类变量和实例变量)和方法。\n", 18 | "- 运算符重载:将多个函数分配给特定的运算符。" 19 | ], 20 | "metadata": {} 21 | }, 22 | { 23 | "cell_type": "markdown", 24 | "source": [ 25 | "本章将从以下几方面来介绍:\n", 26 | "\n", 27 | "一、 类和实例\n", 28 | "* 创建类和实例对象\n", 29 | "* 数据封装\n", 30 | "\n", 31 | "二、访问限制\n", 32 | "\n", 33 | "三、类继承\n", 34 | "* 继承\n", 35 | "* 重载方法\n", 36 | "* 多重继承\n", 37 | "四、获取对象信息\n", 38 | "* type()\n", 39 | "* isinstance()" 40 | ], 41 | "metadata": {} 42 | }, 43 | { 44 | "cell_type": "markdown", 45 | "source": [ 46 | "### 1. 类和实例\n", 47 | "面向对象最重要的概念就是类(Class)和实例(Instance),类是抽象的模板,比如Student类,而实例是根据类创建出来的一个个具体的“对象”,每个对象都拥有相同的方法,但各自的数据可能不同。" 48 | ], 49 | "metadata": {} 50 | }, 51 | { 52 | "cell_type": "markdown", 53 | "source": [ 54 | "#### 1.1 创建类和实例对象" 55 | ], 56 | "metadata": {} 57 | }, 58 | { 59 | "cell_type": "markdown", 60 | "source": [ 61 | "这里以Student类为例,在Python中,通过class关键字来定义类:" 62 | ], 63 | "metadata": {} 64 | }, 65 | { 66 | "cell_type": "code", 67 | "source": [ 68 | "class Student(object):\n", 69 | " pass" 70 | ], 71 | "outputs": [], 72 | "execution_count": 1, 73 | "metadata": { 74 | "collapsed": true 75 | } 76 | }, 77 | { 78 | "cell_type": "markdown", 79 | "source": [ 80 | "class后面紧接着是类名,即Student,类名通常是大写开头的单词,紧接着是(object),表示该类是从哪个类继承下来的。通常,如果没有合适的继承类,就使用object类,这是所有类最终都会继承的类。" 81 | ], 82 | "metadata": {} 83 | }, 84 | { 85 | "cell_type": "markdown", 86 | "source": [ 87 | "定义好了Student类,就可以根据Student类创建出Student的实例,创建实例是通过类名+()实现的" 88 | ], 89 | "metadata": {} 90 | }, 91 | { 92 | "cell_type": "code", 93 | "source": [ 94 | "bart = Student() # 创建Student类的实例\n", 95 | "print(bart)\n", 96 | "print(Student)" 97 | ], 98 | "outputs": [ 99 | { 100 | "output_type": "stream", 101 | "name": "stdout", 102 | "text": [ 103 | "<__main__.Student object at 0x00000182D5B8FCF8>\n", 104 | "\n" 105 | ] 106 | } 107 | ], 108 | "execution_count": 2, 109 | "metadata": {} 110 | }, 111 | { 112 | "cell_type": "markdown", 113 | "source": [ 114 | "可以看到,变量bart指向的就是一个Student的实例,后面的0x000001FB57EBDCF8是内存地址,每个object的地址都不一样,而Student本身则是一个类" 115 | ], 116 | "metadata": {} 117 | }, 118 | { 119 | "cell_type": "markdown", 120 | "source": [ 121 | "可以自由地给一个实例变量绑定属性" 122 | ], 123 | "metadata": {} 124 | }, 125 | { 126 | "cell_type": "code", 127 | "source": [ 128 | "# 比如:给实例bart绑定一个name属性:\n", 129 | "bart.name = 'Bart Simpson'\n", 130 | "bart.name" 131 | ], 132 | "outputs": [ 133 | { 134 | "output_type": "execute_result", 135 | "execution_count": 3, 136 | "data": { 137 | "text/plain": [ 138 | "'Bart Simpson'" 139 | ] 140 | }, 141 | "metadata": {} 142 | } 143 | ], 144 | "execution_count": 3, 145 | "metadata": {} 146 | }, 147 | { 148 | "cell_type": "markdown", 149 | "source": [ 150 | "由于类可以起到模板的作用,因此,可以在创建实例的时候,把一些我们认为必须绑定的属性强制填写进去。通过定义一个特殊的__init__方法,在创建实例的时候,就把name,score等属性绑上去:" 151 | ], 152 | "metadata": {} 153 | }, 154 | { 155 | "cell_type": "code", 156 | "source": [ 157 | "class Student(object):\n", 158 | "\n", 159 | " def __init__(self, name, score):\n", 160 | " self.name = name\n", 161 | " self.score = score" 162 | ], 163 | "outputs": [], 164 | "execution_count": 4, 165 | "metadata": { 166 | "collapsed": true 167 | } 168 | }, 169 | { 170 | "cell_type": "markdown", 171 | "source": [ 172 | "注意到\\__init\\__方法的第一个参数永远是self,表示创建的实例本身,因此,在\\__init\\__方法内部,就可以把各种属性绑定到self,因为self就指向创建的实例本身。有了\\__init\\__方法,在创建实例的时候,就不能传入空的参数了,必须传入与\\__init\\__方法匹配的参数,但self不需要传,Python解释器自己会把实例变量传进去" 173 | ], 174 | "metadata": {} 175 | }, 176 | { 177 | "cell_type": "code", 178 | "source": [ 179 | "bart = Student('Bart Simpson',60)\n", 180 | "print(bart.name)\n", 181 | "print(bart.score)" 182 | ], 183 | "outputs": [ 184 | { 185 | "output_type": "stream", 186 | "name": "stdout", 187 | "text": [ 188 | "Bart Simpson\n", 189 | "60\n" 190 | ] 191 | } 192 | ], 193 | "execution_count": 5, 194 | "metadata": {} 195 | }, 196 | { 197 | "cell_type": "markdown", 198 | "source": [ 199 | "和普通的函数相比,在类中定义的函数只有一点不同,就是第一个参数永远是实例变量self,并且,调用时,不用传递该参数。除此之外,类的方法和普通函数没有什么区别,所以,仍然可以用默认参数、可变参数、关键字参数和命名关键字参数。" 200 | ], 201 | "metadata": {} 202 | }, 203 | { 204 | "cell_type": "markdown", 205 | "source": [ 206 | "#### 1.2 数据封装\n", 207 | "面向对象编程的一个重要特点就是数据封装。在上面的Student类中,每个实例就拥有各自的name和score这些数据。访问这些数据,可以直接在Student类的内部定义访问数据的函数,这样,就把“数据”给封装起来了。这些封装数据的函数是和Student类本身是关联起来的,我们称之为类的方法:" 208 | ], 209 | "metadata": {} 210 | }, 211 | { 212 | "cell_type": "code", 213 | "source": [ 214 | "class Student(object):\n", 215 | "\n", 216 | " def __init__(self, name, score):\n", 217 | " self.name = name\n", 218 | " self.score = score\n", 219 | "\n", 220 | " def print_score(self):\n", 221 | " print('%s: %s' % (self.name, self.score))" 222 | ], 223 | "outputs": [], 224 | "execution_count": 6, 225 | "metadata": { 226 | "collapsed": true 227 | } 228 | }, 229 | { 230 | "cell_type": "markdown", 231 | "source": [ 232 | "要定义一个方法,除了第一个参数是self外,其他和普通函数一样。要调用一个方法,只需要在实例变量上直接调用,除了self不用传递,其他参数正常传入:" 233 | ], 234 | "metadata": {} 235 | }, 236 | { 237 | "cell_type": "code", 238 | "source": [ 239 | "bart = Student('Kobe',89) # 创建实例\n", 240 | "bart.print_score() # 实例变量调用类方法" 241 | ], 242 | "outputs": [ 243 | { 244 | "output_type": "stream", 245 | "name": "stdout", 246 | "text": [ 247 | "Kobe: 89\n" 248 | ] 249 | } 250 | ], 251 | "execution_count": 7, 252 | "metadata": {} 253 | }, 254 | { 255 | "cell_type": "markdown", 256 | "source": [ 257 | "### 2. 访问限制" 258 | ], 259 | "metadata": {} 260 | }, 261 | { 262 | "cell_type": "markdown", 263 | "source": [ 264 | "在Class内部,可以有属性和方法,而外部代码可以通过直接调用实例变量的方法来操作数据,这样,就隐藏了内部的复杂逻辑。但是,从前面Student类的定义来看,外部代码还是可以自由地修改一个实例的name、score属性,如下所示:" 265 | ], 266 | "metadata": {} 267 | }, 268 | { 269 | "cell_type": "code", 270 | "source": [ 271 | "bart = Student('Bart',88)\n", 272 | "print(bart.score)\n", 273 | "bart.score=90\n", 274 | "print(bart.score)" 275 | ], 276 | "outputs": [ 277 | { 278 | "output_type": "stream", 279 | "name": "stdout", 280 | "text": [ 281 | "88\n", 282 | "90\n" 283 | ] 284 | } 285 | ], 286 | "execution_count": 8, 287 | "metadata": {} 288 | }, 289 | { 290 | "cell_type": "markdown", 291 | "source": [ 292 | "如果要让内部属性不被外部访问,可以把属性的名称前加上两个下划线\\__,在Python中,实例的变量名如果以\\__开头,就变成了一个私有变量(private),只有内部可以访问,外部不能访问,所以,我们Student类改为以下形式" 293 | ], 294 | "metadata": {} 295 | }, 296 | { 297 | "cell_type": "code", 298 | "source": [ 299 | "class Student(object):\n", 300 | "\n", 301 | " def __init__(self, name, score):\n", 302 | " self.__name = name # 变为私有变量\n", 303 | " self.__score = score\n", 304 | "\n", 305 | " def print_score(self):\n", 306 | " print('%s: %s' % (self.__name, self.__score))" 307 | ], 308 | "outputs": [], 309 | "execution_count": 13, 310 | "metadata": { 311 | "collapsed": true 312 | } 313 | }, 314 | { 315 | "cell_type": "markdown", 316 | "source": [ 317 | "修改完后,对于外部代码来说,已经无法从外部访问实例变量.\\__name和实例变量.\\__score了。这样就确保了外部代码不能随意修改对象内部的状态,这样通过访问限制的保护,代码更加健壮。" 318 | ], 319 | "metadata": {} 320 | }, 321 | { 322 | "cell_type": "markdown", 323 | "source": [ 324 | "要想在外部获取name和score,可以给类添加get_name和get_score方法;同理,想在外部修改,则可添加set方法,如下所示:" 325 | ], 326 | "metadata": {} 327 | }, 328 | { 329 | "cell_type": "code", 330 | "source": [ 331 | "class Student(object):\n", 332 | "\n", 333 | " def __init__(self, name, score):\n", 334 | " self.__name = name # 变为私有变量\n", 335 | " self.__score = score\n", 336 | "\n", 337 | " def print_score(self):\n", 338 | " print('%s: %s' % (self.__name, self.__score))\n", 339 | " \n", 340 | " def get_name(self):\n", 341 | " return self.__name\n", 342 | " \n", 343 | " def get_score(self):\n", 344 | " return self.__score\n", 345 | " \n", 346 | " def set_name(self,name):\n", 347 | " self.__name = name\n", 348 | " \n", 349 | " def set_score(self,score):\n", 350 | " self.__score = score" 351 | ], 352 | "outputs": [], 353 | "execution_count": 15, 354 | "metadata": { 355 | "collapsed": true 356 | } 357 | }, 358 | { 359 | "cell_type": "markdown", 360 | "source": [ 361 | "值得注意的是,在Python中,变量名为\\__xxx\\__的,也就是以双下划线开头,并且以双下划线结尾的,是特殊变量,特殊变量是可以直接访问的,不是私有变量。" 362 | ], 363 | "metadata": {} 364 | }, 365 | { 366 | "cell_type": "markdown", 367 | "source": [ 368 | "最后再注意下面这种错误的写法:" 369 | ], 370 | "metadata": {} 371 | }, 372 | { 373 | "cell_type": "code", 374 | "source": [ 375 | "bart = Student('Bart',88)\n", 376 | "print(bart.get_name())\n", 377 | "bart.__name = 'New Name' # 设置__name变量\n", 378 | "print(bart.__name)" 379 | ], 380 | "outputs": [ 381 | { 382 | "output_type": "stream", 383 | "name": "stdout", 384 | "text": [ 385 | "Bart\n", 386 | "New Name\n" 387 | ] 388 | } 389 | ], 390 | "execution_count": 17, 391 | "metadata": {} 392 | }, 393 | { 394 | "cell_type": "markdown", 395 | "source": [ 396 | "表面上看,外部代码“成功”地设置了\\__name变量,但实际上这个\\__name变量和class内部的\\__name变量不是一个变量!内部的\\__name变量已经被Python解释器保护起来,而外部代码给bart新增了一个\\__name变量。调用get_name()方法即可知道:" 397 | ], 398 | "metadata": {} 399 | }, 400 | { 401 | "cell_type": "code", 402 | "source": [ 403 | "bart.get_name()" 404 | ], 405 | "outputs": [ 406 | { 407 | "output_type": "execute_result", 408 | "execution_count": 18, 409 | "data": { 410 | "text/plain": [ 411 | "'Bart'" 412 | ] 413 | }, 414 | "metadata": {} 415 | } 416 | ], 417 | "execution_count": 18, 418 | "metadata": {} 419 | }, 420 | { 421 | "cell_type": "markdown", 422 | "source": [ 423 | "### 3. 类继承\n", 424 | "继承用于指定一个类将从其父类获取其大部分或全部功能。 它是面向对象编程的一个特征。 这是一个非常强大的功能,方便用户对现有类进行几个或多个修改来创建一个新的类。新类称为子类或派生类,从其继承属性的主类称为基类或父类。" 425 | ], 426 | "metadata": {} 427 | }, 428 | { 429 | "cell_type": "markdown", 430 | "source": [ 431 | "子类或派生类继承父类的功能,向其添加新功能。 它有助于代码的可重用性。如下图所示:\n", 432 | "![image.png](attachment:image.png)" 433 | ], 434 | "metadata": {} 435 | }, 436 | { 437 | "cell_type": "markdown", 438 | "source": [ 439 | "#### 3.1 继承\n", 440 | "在OOP程序设计中,当我们定义一个class的时候,可以从某个现有的class继承,新的class称为子类(Subclass),而被继承的class称为基类、父类或超类。" 441 | ], 442 | "metadata": {} 443 | }, 444 | { 445 | "cell_type": "markdown", 446 | "source": [ 447 | "比如,我们已经编写了一个名为Animal的class,有一个run()方法可以直接打印:" 448 | ], 449 | "metadata": {} 450 | }, 451 | { 452 | "cell_type": "code", 453 | "source": [ 454 | "class Animal(object):\n", 455 | " def run(self):\n", 456 | " print('I am a animal')" 457 | ], 458 | "outputs": [], 459 | "execution_count": 19, 460 | "metadata": { 461 | "collapsed": true 462 | } 463 | }, 464 | { 465 | "cell_type": "markdown", 466 | "source": [ 467 | "当我们需要编写Dog和Cat类时,就可以直接从Animal类继承:" 468 | ], 469 | "metadata": {} 470 | }, 471 | { 472 | "cell_type": "code", 473 | "source": [ 474 | "# 对于Dog来说,Animal就是它的父类,对于Animal来说,Dog就是它的子类。Cat和Dog类似。\n", 475 | "class Dog(Animal):\n", 476 | " pass\n", 477 | "\n", 478 | "class Cat(Animal):\n", 479 | " pass" 480 | ], 481 | "outputs": [], 482 | "execution_count": 20, 483 | "metadata": { 484 | "collapsed": true 485 | } 486 | }, 487 | { 488 | "cell_type": "markdown", 489 | "source": [ 490 | "对于子类来说,它获得了父类的所有功能。由于Animial实现了run()方法,因此,Dog和Cat作为它的子,就自动拥有了run()方法:" 491 | ], 492 | "metadata": {} 493 | }, 494 | { 495 | "cell_type": "code", 496 | "source": [ 497 | "dog = Dog()\n", 498 | "dog.run()\n", 499 | "\n", 500 | "cat = Cat()\n", 501 | "cat.run()" 502 | ], 503 | "outputs": [ 504 | { 505 | "output_type": "stream", 506 | "name": "stdout", 507 | "text": [ 508 | "I am a animal\n", 509 | "I am a animal\n" 510 | ] 511 | } 512 | ], 513 | "execution_count": 21, 514 | "metadata": {} 515 | }, 516 | { 517 | "cell_type": "markdown", 518 | "source": [ 519 | "除此之外,还可以对子类增加一些方法,比如:" 520 | ], 521 | "metadata": {} 522 | }, 523 | { 524 | "cell_type": "code", 525 | "source": [ 526 | "class Dog(Animal):\n", 527 | " def eat(self): # 添加新方法\n", 528 | " print('I like eating bones')" 529 | ], 530 | "outputs": [], 531 | "execution_count": 43, 532 | "metadata": { 533 | "collapsed": true 534 | } 535 | }, 536 | { 537 | "cell_type": "code", 538 | "source": [ 539 | "dog = Dog()\n", 540 | "dog.run()\n", 541 | "dog.eat()" 542 | ], 543 | "outputs": [ 544 | { 545 | "output_type": "stream", 546 | "name": "stdout", 547 | "text": [ 548 | "I am a animal\n", 549 | "I like eating bones\n" 550 | ] 551 | } 552 | ], 553 | "execution_count": 44, 554 | "metadata": {} 555 | }, 556 | { 557 | "cell_type": "markdown", 558 | "source": [ 559 | "#### 3.2 重载方法\n", 560 | "可以随时重载父类的方法。" 561 | ], 562 | "metadata": {} 563 | }, 564 | { 565 | "cell_type": "code", 566 | "source": [ 567 | "class Animal(object):\n", 568 | " def run(self):\n", 569 | " print('I am a animal')\n", 570 | " \n", 571 | "class Dog(object):\n", 572 | " def run(self): # 重载方法\n", 573 | " print('I am a dog')\n", 574 | "\n", 575 | "dog = Dog()\n", 576 | "dog.run()" 577 | ], 578 | "outputs": [ 579 | { 580 | "output_type": "stream", 581 | "name": "stdout", 582 | "text": [ 583 | "I am a dog\n" 584 | ] 585 | } 586 | ], 587 | "execution_count": 45, 588 | "metadata": {} 589 | }, 590 | { 591 | "cell_type": "markdown", 592 | "source": [ 593 | "下表列出了可以在自己的类中覆盖的一些通用方法:\n", 594 | "![image.png](attachment:image.png)" 595 | ], 596 | "metadata": {} 597 | }, 598 | { 599 | "cell_type": "markdown", 600 | "source": [ 601 | "#### 3.3 多重继承\n", 602 | "在多重继承中,所有基类的特征都被继承到派生类中。多重继承的语法类似于单继承。" 603 | ], 604 | "metadata": {} 605 | }, 606 | { 607 | "cell_type": "code", 608 | "source": [ 609 | "# 多重继承的示例\n", 610 | "class Base1:\n", 611 | " pass\n", 612 | "\n", 613 | "class Base2:\n", 614 | " pass\n", 615 | "\n", 616 | "class MultiDerived(Base1, Base2): # MultiDerived继承Base1和Base2\n", 617 | " pass" 618 | ], 619 | "outputs": [], 620 | "execution_count": 46, 621 | "metadata": { 622 | "collapsed": true 623 | } 624 | }, 625 | { 626 | "cell_type": "markdown", 627 | "source": [ 628 | "![image.png](attachment:image.png)" 629 | ], 630 | "metadata": {} 631 | }, 632 | { 633 | "cell_type": "code", 634 | "source": [ 635 | "# 多重继承举例\n", 636 | "class Animal(object):\n", 637 | " def run(self):\n", 638 | " print('I am a animal')\n", 639 | "\n", 640 | "class Dog(object):\n", 641 | " def eat(self):\n", 642 | " print('I like eat bones')\n", 643 | " \n", 644 | "class Dog_son(Animal,Dog): # Dog_son类同时继承Animal类和Dog类,Dog_son拥有Animal和Dog中所有的方法\n", 645 | " def run(self):\n", 646 | " print('666666666') # 而且多重继承中,同样可以重写父类的方法\n", 647 | " def p(self):\n", 648 | " print('hello')\n", 649 | "\n", 650 | "dog_son = Dog_son()\n", 651 | "dog_son.p()\n", 652 | "dog_son.eat()\n", 653 | "dog_son.run()" 654 | ], 655 | "outputs": [ 656 | { 657 | "output_type": "stream", 658 | "name": "stdout", 659 | "text": [ 660 | "hello\n", 661 | "I like eat bones\n", 662 | "666666666\n" 663 | ] 664 | } 665 | ], 666 | "execution_count": 51, 667 | "metadata": {} 668 | }, 669 | { 670 | "cell_type": "markdown", 671 | "source": [ 672 | "#### 3.4 多级继承\n", 673 | "另一方面,我们也可以继承一个派生类的形式。这被称为多级继承。 它可以在Python中有任何的深度(层级)。在多级继承中,基类和派生类的特性被继承到新的派生类中。" 674 | ], 675 | "metadata": {} 676 | }, 677 | { 678 | "cell_type": "code", 679 | "source": [ 680 | "# 多级继承示例\n", 681 | "class Base:\n", 682 | " pass\n", 683 | "\n", 684 | "class Derived1(Base):\n", 685 | " pass\n", 686 | "\n", 687 | "class Derived2(Derived1):\n", 688 | " pass" 689 | ], 690 | "outputs": [], 691 | "execution_count": 47, 692 | "metadata": { 693 | "collapsed": true 694 | } 695 | }, 696 | { 697 | "cell_type": "markdown", 698 | "source": [ 699 | "![image.png](attachment:image.png)" 700 | ], 701 | "metadata": {} 702 | }, 703 | { 704 | "cell_type": "code", 705 | "source": [ 706 | "# 多级继承举例\n", 707 | "class Animal(object):\n", 708 | " def run(self):\n", 709 | " print('I am a animal')\n", 710 | "\n", 711 | "class Dog(Animal):\n", 712 | " def eat(self):\n", 713 | " print('I like eat bones')\n", 714 | " \n", 715 | "class Dog_son(Dog): # Dog_son继承Dog类,Dog类继承Animal类\n", 716 | " def run(self):\n", 717 | " print('666666666') # 多级继承中,同样可以重写父类的方法\n", 718 | " def p(self):\n", 719 | " print('hello')\n", 720 | "# 与多重继承相似,dog_son同样拥有Dog和Animal类中的方法\n", 721 | "dog_son = Dog_son()\n", 722 | "dog_son.p()\n", 723 | "dog_son.eat()\n", 724 | "dog_son.run()" 725 | ], 726 | "outputs": [ 727 | { 728 | "output_type": "stream", 729 | "name": "stdout", 730 | "text": [ 731 | "hello\n", 732 | "I like eat bones\n", 733 | "666666666\n" 734 | ] 735 | } 736 | ], 737 | "execution_count": 54, 738 | "metadata": {} 739 | }, 740 | { 741 | "cell_type": "markdown", 742 | "source": [ 743 | "### 4. 获取对象信息" 744 | ], 745 | "metadata": {} 746 | }, 747 | { 748 | "cell_type": "markdown", 749 | "source": [ 750 | "当我们拿到一个对象的引用时,可以通过以下方法得知对象的类型及包含的方法" 751 | ], 752 | "metadata": {} 753 | }, 754 | { 755 | "cell_type": "markdown", 756 | "source": [ 757 | "#### 4.1 type()" 758 | ], 759 | "metadata": {} 760 | }, 761 | { 762 | "cell_type": "code", 763 | "source": [ 764 | "# 基本类型都可以用type()判断\n", 765 | "print(type(123))\n", 766 | "print(type('str'))\n", 767 | "print(type(None))" 768 | ], 769 | "outputs": [ 770 | { 771 | "output_type": "stream", 772 | "name": "stdout", 773 | "text": [ 774 | "\n", 775 | "\n", 776 | "\n" 777 | ] 778 | } 779 | ], 780 | "execution_count": 27, 781 | "metadata": {} 782 | }, 783 | { 784 | "cell_type": "code", 785 | "source": [ 786 | "# 如果一个变量指向函数或者类,也可以用type()判断\n", 787 | "print(type(abs))\n", 788 | "print(type(dog))" 789 | ], 790 | "outputs": [ 791 | { 792 | "output_type": "stream", 793 | "name": "stdout", 794 | "text": [ 795 | "\n", 796 | "\n" 797 | ] 798 | } 799 | ], 800 | "execution_count": 28, 801 | "metadata": {} 802 | }, 803 | { 804 | "cell_type": "markdown", 805 | "source": [ 806 | "#### 4.2 isinstance()\n", 807 | "对于class的继承关系来说,使用type()就很不方便。我们要判断class的类型,可以使用isinstance()函数" 808 | ], 809 | "metadata": {} 810 | }, 811 | { 812 | "cell_type": "markdown", 813 | "source": [ 814 | "isinstance()判断的是一个对象是否是该类型本身,或者位于该类型的父继承链上。" 815 | ], 816 | "metadata": {} 817 | }, 818 | { 819 | "cell_type": "code", 820 | "source": [ 821 | "# 引用上面的dog类继承Animal类\n", 822 | "print(isinstance(dog,Dog))\n", 823 | "print(isinstance(dog,Animal))" 824 | ], 825 | "outputs": [ 826 | { 827 | "output_type": "stream", 828 | "name": "stdout", 829 | "text": [ 830 | "True\n", 831 | "True\n" 832 | ] 833 | } 834 | ], 835 | "execution_count": 29, 836 | "metadata": {} 837 | }, 838 | { 839 | "cell_type": "code", 840 | "source": [ 841 | "# 能用type()判断的基本类型也可以用isinstance()判断\n", 842 | "print(isinstance('a',str))\n", 843 | "print(isinstance(123,str))" 844 | ], 845 | "outputs": [ 846 | { 847 | "output_type": "stream", 848 | "name": "stdout", 849 | "text": [ 850 | "True\n", 851 | "False\n" 852 | ] 853 | } 854 | ], 855 | "execution_count": 30, 856 | "metadata": {} 857 | }, 858 | { 859 | "cell_type": "code", 860 | "source": [ 861 | "# 还可以判断一个变量是否是某些类型中的一种\n", 862 | "print(isinstance([1,2,3],(list,tuple)))\n", 863 | "print(isinstance((1,2,3),(list,tuple)))" 864 | ], 865 | "outputs": [ 866 | { 867 | "output_type": "stream", 868 | "name": "stdout", 869 | "text": [ 870 | "True\n", 871 | "True\n" 872 | ] 873 | } 874 | ], 875 | "execution_count": 31, 876 | "metadata": {} 877 | }, 878 | { 879 | "cell_type": "markdown", 880 | "source": [ 881 | "#### 4.3 dir()\n", 882 | "如果要获得一个对象的所有属性和方法,可以使用dir()函数,它返回一个包含字符串的list" 883 | ], 884 | "metadata": {} 885 | }, 886 | { 887 | "cell_type": "code", 888 | "source": [ 889 | "# 比如,获得一个str对象的所有属性和方法\n", 890 | "dir('ABC')[0:5] # 值显示前5个结果" 891 | ], 892 | "outputs": [ 893 | { 894 | "output_type": "execute_result", 895 | "execution_count": 34, 896 | "data": { 897 | "text/plain": [ 898 | "['__add__', '__class__', '__contains__', '__delattr__', '__dir__']" 899 | ] 900 | }, 901 | "metadata": {} 902 | } 903 | ], 904 | "execution_count": 34, 905 | "metadata": {} 906 | }, 907 | { 908 | "cell_type": "markdown", 909 | "source": [ 910 | "### 5. 实例属性和类属性" 911 | ], 912 | "metadata": {} 913 | }, 914 | { 915 | "cell_type": "markdown", 916 | "source": [ 917 | "由于Python是动态语言,根据类创建的实例可以任意绑定属性。给实例绑定属性的方法是通过实例变量,或者通过self变量:" 918 | ], 919 | "metadata": {} 920 | }, 921 | { 922 | "cell_type": "code", 923 | "source": [ 924 | "class Animal():\n", 925 | " def __init__(self,name,weight):\n", 926 | " self.name = name\n", 927 | " self.weight = weight\n", 928 | "dog = Animal('hasky',90)\n", 929 | "dog.height = 20 # 这里的height为实例属性\n", 930 | "print(dog.height)" 931 | ], 932 | "outputs": [ 933 | { 934 | "output_type": "stream", 935 | "name": "stdout", 936 | "text": [ 937 | "20\n" 938 | ] 939 | } 940 | ], 941 | "execution_count": 55, 942 | "metadata": {} 943 | }, 944 | { 945 | "cell_type": "markdown", 946 | "source": [ 947 | "在class中定义属性,这种属性是类属性,如下面的tt,归Animal类所有:" 948 | ], 949 | "metadata": {} 950 | }, 951 | { 952 | "cell_type": "code", 953 | "source": [ 954 | "class Animal():\n", 955 | " tt = 'ss'\n", 956 | " def __init__(self,name,weight):\n", 957 | " self.name = name\n", 958 | " self.weight = weight\n", 959 | "print(Animal.tt) # 类属性\n", 960 | "dog = Animal('hasky',90) \n", 961 | "print(dog.tt) \n", 962 | "dog.tt = 'aa'\n", 963 | "print(dog.tt)\n", 964 | "print(Animal.tt)" 965 | ], 966 | "outputs": [ 967 | { 968 | "output_type": "stream", 969 | "name": "stdout", 970 | "text": [ 971 | "ss\n", 972 | "ss\n", 973 | "aa\n", 974 | "ss\n" 975 | ] 976 | } 977 | ], 978 | "execution_count": 58, 979 | "metadata": {} 980 | }, 981 | { 982 | "cell_type": "markdown", 983 | "source": [ 984 | "可以看到,我们创建了Animal类的一个类属性tt,所有实例都可以访问该属性,而在编写程序的时候,千万不要对实例属性和类属性使用相同的名字,因为相同名称的实例属性将屏蔽掉类属性,但是当你删除实例属性后,再使用相同的名称,访问到的将是类属性。" 985 | ], 986 | "metadata": {} 987 | }, 988 | { 989 | "cell_type": "code", 990 | "source": [], 991 | "outputs": [], 992 | "execution_count": null, 993 | "metadata": { 994 | "collapsed": true 995 | } 996 | } 997 | ], 998 | "metadata": { 999 | "kernelspec": { 1000 | "name": "python3", 1001 | "language": "python", 1002 | "display_name": "Python 3" 1003 | }, 1004 | "language_info": { 1005 | "name": "python", 1006 | "version": "3.6.9", 1007 | "mimetype": "text/x-python", 1008 | "codemirror_mode": { 1009 | "name": "ipython", 1010 | "version": 3 1011 | }, 1012 | "pygments_lexer": "ipython3", 1013 | "nbconvert_exporter": "python", 1014 | "file_extension": ".py" 1015 | }, 1016 | "varInspector": { 1017 | "cols": { 1018 | "lenName": 16, 1019 | "lenType": 16, 1020 | "lenVar": 40 1021 | }, 1022 | "kernels_config": { 1023 | "python": { 1024 | "delete_cmd_postfix": "", 1025 | "delete_cmd_prefix": "del ", 1026 | "library": "var_list.py", 1027 | "varRefreshCmd": "print(var_dic_list())" 1028 | }, 1029 | "r": { 1030 | "delete_cmd_postfix": ") ", 1031 | "delete_cmd_prefix": "rm(", 1032 | "library": "var_list.r", 1033 | "varRefreshCmd": "cat(var_dic_list()) " 1034 | } 1035 | }, 1036 | "types_to_exclude": [ 1037 | "module", 1038 | "function", 1039 | "builtin_function_or_method", 1040 | "instance", 1041 | "_Feature" 1042 | ], 1043 | "window_display": false 1044 | }, 1045 | "kernel_info": { 1046 | "name": "python3" 1047 | }, 1048 | "nteract": { 1049 | "version": "0.14.5" 1050 | } 1051 | }, 1052 | "nbformat": 4, 1053 | "nbformat_minor": 2 1054 | } -------------------------------------------------------------------------------- /7 Python 类与对象.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetalkdata/python_script-manual/4720aec496fe9b6f2b5e5fa92cf6aace864aac82/7 Python 类与对象.pdf -------------------------------------------------------------------------------- /8 Python 装饰器.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# 第8章 python装饰器\n", 8 | "装饰器本质上是一个Python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象。它经常用于有切面需求的场景,比如:插入日志、性能测试、事务处理、缓存、权限校验等场景。装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量与函数功能本身无关的雷同代码并继续重用。" 9 | ] 10 | }, 11 | { 12 | "cell_type": "markdown", 13 | "metadata": {}, 14 | "source": [ 15 | "本章将从以下方面来介绍Python中的装饰器:\n", 16 | "\n", 17 | "* 函数装饰器\n", 18 | "\n", 19 | "* 类装饰器\n", 20 | "* 内置装饰器\n", 21 | "* 装饰器链\n", 22 | "* 需要注意的地方" 23 | ] 24 | }, 25 | { 26 | "cell_type": "markdown", 27 | "metadata": {}, 28 | "source": [ 29 | "### 1. 函数装饰器" 30 | ] 31 | }, 32 | { 33 | "cell_type": "markdown", 34 | "metadata": {}, 35 | "source": [ 36 | "#### 1.1 简单装饰器" 37 | ] 38 | }, 39 | { 40 | "cell_type": "code", 41 | "execution_count": 2, 42 | "metadata": {}, 43 | "outputs": [ 44 | { 45 | "name": "stdout", 46 | "output_type": "stream", 47 | "text": [ 48 | "这是一个简单的装饰器\n", 49 | "i am foo\n" 50 | ] 51 | } 52 | ], 53 | "source": [ 54 | "def use_logging(func):\n", 55 | "\n", 56 | " def wrapper():\n", 57 | " print('这是一个简单的装饰器')\n", 58 | " return func() # 把 foo 当做参数传递进来时,执行func()就相当于执行foo()\n", 59 | " return wrapper\n", 60 | "\n", 61 | "def foo():\n", 62 | " print('i am foo')\n", 63 | "\n", 64 | "foo = use_logging(foo) # 因为装饰器 use_logging(foo) 返回的是函数对象 wrapper,这条语句相当于 foo = wrapper\n", 65 | "foo() # 执行foo()就相当于执行 wrapper()" 66 | ] 67 | }, 68 | { 69 | "cell_type": "markdown", 70 | "metadata": {}, 71 | "source": [ 72 | "#### 1.2 @语法糖\n", 73 | "@ 符号就是装饰器的语法糖,它放在函数开始定义的地方,这样就可以省略最后一步再次赋值的操作。" 74 | ] 75 | }, 76 | { 77 | "cell_type": "code", 78 | "execution_count": 3, 79 | "metadata": {}, 80 | "outputs": [ 81 | { 82 | "name": "stdout", 83 | "output_type": "stream", 84 | "text": [ 85 | "这是一个简单的装饰器\n", 86 | "i am foo\n" 87 | ] 88 | } 89 | ], 90 | "source": [ 91 | "def use_logging(func):\n", 92 | "\n", 93 | " def wrapper():\n", 94 | " print('这是一个简单的装饰器')\n", 95 | " return func() # 把 foo 当做参数传递进来时,执行func()就相当于执行foo()\n", 96 | " return wrapper\n", 97 | "\n", 98 | "@use_logging\n", 99 | "def foo():\n", 100 | " print('i am foo')\n", 101 | "\n", 102 | "foo() # 执行foo()就相当于执行 wrapper()" 103 | ] 104 | }, 105 | { 106 | "cell_type": "markdown", 107 | "metadata": {}, 108 | "source": [ 109 | "如上所示,有了 @ ,我们就可以省去foo = use_logging(foo)这一句了,直接调用 foo() 即可得到想要的结果。foo() 函数不需要做任何修改,只需在定义的地方加上装饰器,调用的时候还是和以前一样,如果我们有其他的类似函数,我们可以继续调用装饰器来修饰函数,而不用重复修改函数或者增加新的封装。这样,我们就提高了程序的可重复利用性,并增加了程序的可读性。" 110 | ] 111 | }, 112 | { 113 | "cell_type": "markdown", 114 | "metadata": {}, 115 | "source": [ 116 | "#### 1.3 \\*args、**kwargs" 117 | ] 118 | }, 119 | { 120 | "cell_type": "markdown", 121 | "metadata": {}, 122 | "source": [ 123 | "如果我的业务逻辑函数 foo 需要参数该怎么办?比如:" 124 | ] 125 | }, 126 | { 127 | "cell_type": "code", 128 | "execution_count": 4, 129 | "metadata": { 130 | "collapsed": true 131 | }, 132 | "outputs": [], 133 | "source": [ 134 | "def foo(name):\n", 135 | " print(\"i am %s\" % name)" 136 | ] 137 | }, 138 | { 139 | "cell_type": "markdown", 140 | "metadata": {}, 141 | "source": [ 142 | "这时,我们可以在定义wrapper函数的时候指定参数。并且当装饰器不知道 foo 到底有多少个参数时,我们可以用 *args 来代替" 143 | ] 144 | }, 145 | { 146 | "cell_type": "code", 147 | "execution_count": null, 148 | "metadata": { 149 | "collapsed": true 150 | }, 151 | "outputs": [], 152 | "source": [ 153 | "def wrapper(*args):\n", 154 | " print('test')\n", 155 | " return func(*args)\n", 156 | " return wrapper" 157 | ] 158 | }, 159 | { 160 | "cell_type": "markdown", 161 | "metadata": {}, 162 | "source": [ 163 | "如此一来,不管foo定义了多少个参数,我们都可以完整地传递到 func 中去。这样就不影响 foo 的业务逻辑了。这时你可能还有疑问,如果 foo 函数还定义了一些关键字参数呢?比如:" 164 | ] 165 | }, 166 | { 167 | "cell_type": "code", 168 | "execution_count": null, 169 | "metadata": { 170 | "collapsed": true 171 | }, 172 | "outputs": [], 173 | "source": [ 174 | "def foo(name, age=None, height=None):\n", 175 | " print(\"I am %s, age %s, height %s\" % (name, age, height))" 176 | ] 177 | }, 178 | { 179 | "cell_type": "markdown", 180 | "metadata": {}, 181 | "source": [ 182 | "这时,我们就可以把 wrapper 函数指定关键字函数:" 183 | ] 184 | }, 185 | { 186 | "cell_type": "code", 187 | "execution_count": null, 188 | "metadata": { 189 | "collapsed": true 190 | }, 191 | "outputs": [], 192 | "source": [ 193 | "def wrapper(*args, **kwargs):\n", 194 | " # args是一个数组,kwargs一个字典\n", 195 | " print('test')\n", 196 | " return func(*args, **kwargs)\n", 197 | " return wrapper" 198 | ] 199 | }, 200 | { 201 | "cell_type": "markdown", 202 | "metadata": {}, 203 | "source": [ 204 | "### 1.4 类方法的函数装饰器" 205 | ] 206 | }, 207 | { 208 | "cell_type": "code", 209 | "execution_count": 4, 210 | "metadata": {}, 211 | "outputs": [ 212 | { 213 | "name": "stdout", 214 | "output_type": "stream", 215 | "text": [ 216 | "0.8001229763031006\n" 217 | ] 218 | } 219 | ], 220 | "source": [ 221 | "import time\n", 222 | "\n", 223 | "def decorator(func):\n", 224 | " def wrapper(me_instance):\n", 225 | " start_time = time.time()\n", 226 | " func(me_instance)\n", 227 | " end_time = time.time()\n", 228 | " print(end_time - start_time)\n", 229 | " return wrapper\n", 230 | "\n", 231 | "class Method(object):\n", 232 | " \n", 233 | " @decorator\n", 234 | " def func(self):\n", 235 | " time.sleep(0.8)\n", 236 | " \n", 237 | "p1 = Method()\n", 238 | "p1.func() #函数调用" 239 | ] 240 | }, 241 | { 242 | "cell_type": "markdown", 243 | "metadata": {}, 244 | "source": [ 245 | "对于类方法来说,都会有一个默认的参数self,它实际表示的是类的一个实例,所以在装饰器的内部函数wrapper也要传入一个参数me_instance就表示将类的实例p1传给wrapper,其他的用法都和函数装饰器相同。" 246 | ] 247 | }, 248 | { 249 | "cell_type": "markdown", 250 | "metadata": {}, 251 | "source": [ 252 | "### 2. 类装饰器\n", 253 | "装饰器不仅可以是函数,还可以是类,相比函数装饰器,类装饰器具有灵活度大、高内聚、封装性等优点。使用类装饰器主要依靠类的\\__call\\__方法,当使用 @ 形式将装饰器附加到函数上时,就会调用此方法。" 254 | ] 255 | }, 256 | { 257 | "cell_type": "code", 258 | "execution_count": 5, 259 | "metadata": {}, 260 | "outputs": [ 261 | { 262 | "name": "stdout", 263 | "output_type": "stream", 264 | "text": [ 265 | "decorator start\n", 266 | "func\n", 267 | "decorator end\n" 268 | ] 269 | } 270 | ], 271 | "source": [ 272 | "class Decorator(object):\n", 273 | " def __init__(self,f):\n", 274 | " self.f = f\n", 275 | " def __call__(self): # __call__是一个特殊方法,它可将一个类实例变成一个可调用对象\n", 276 | " print(\"decorator start\")\n", 277 | " self.f()\n", 278 | " print(\"decorator end\")\n", 279 | " \n", 280 | "@Decorator\n", 281 | "def func():\n", 282 | " print(\"func\")\n", 283 | " \n", 284 | "func()" 285 | ] 286 | }, 287 | { 288 | "cell_type": "markdown", 289 | "metadata": {}, 290 | "source": [ 291 | "要使用类装饰器必须实现类中的\\__call\\__()方法,就相当于将实例变成了一个方法。" 292 | ] 293 | }, 294 | { 295 | "cell_type": "markdown", 296 | "metadata": {}, 297 | "source": [ 298 | "### 3. 内置装饰器\n", 299 | "python常用内置装饰器有属性(property),类方法(classmethod),静态方法(staticmethod)" 300 | ] 301 | }, 302 | { 303 | "cell_type": "markdown", 304 | "metadata": {}, 305 | "source": [ 306 | "#### 3.1 @property\n", 307 | "使调用类中的方法像引用类中的字段属性一样" 308 | ] 309 | }, 310 | { 311 | "cell_type": "code", 312 | "execution_count": 17, 313 | "metadata": {}, 314 | "outputs": [ 315 | { 316 | "name": "stdout", 317 | "output_type": "stream", 318 | "text": [ 319 | "通过实例引用属性\n", 320 | "Tom\n", 321 | "像引用属性一样调用@property修饰的方法\n", 322 | "hello Tom\n" 323 | ] 324 | } 325 | ], 326 | "source": [ 327 | "class TestClass:\n", 328 | " name = 'test'\n", 329 | " def __init__(self,name):\n", 330 | " self.name = name\n", 331 | " \n", 332 | " @property\n", 333 | " def sayHello(self):\n", 334 | " print(\"hello\",self.name)\n", 335 | " \n", 336 | "cls = TestClass('Tom')\n", 337 | "print('通过实例引用属性')\n", 338 | "print(cls.name)\n", 339 | "print('像引用属性一样调用@property修饰的方法')\n", 340 | "cls.sayHello" 341 | ] 342 | }, 343 | { 344 | "cell_type": "markdown", 345 | "metadata": {}, 346 | "source": [ 347 | "下面再引用一个例子来介绍property的更常用的用法:" 348 | ] 349 | }, 350 | { 351 | "cell_type": "code", 352 | "execution_count": 23, 353 | "metadata": {}, 354 | "outputs": [ 355 | { 356 | "name": "stdout", 357 | "output_type": "stream", 358 | "text": [ 359 | "5\n", 360 | "6\n", 361 | "30\n", 362 | "22\n" 363 | ] 364 | } 365 | ], 366 | "source": [ 367 | "# 假设现在有个矩形,可以设置其宽、高。\n", 368 | "# 如果需要面积,我们可以使用类似于area()的方法来计算。\n", 369 | "# 如果需要周长,我们可以使用类似于perimeter()的方法来计算。\n", 370 | "# 对于Python这种动态语言来说,可以用perperty()加以包装:\n", 371 | "class Rectangle(object):\n", 372 | " def __init__ (self,width,height):\n", 373 | " self.__width = width\n", 374 | " self.__height = height\n", 375 | "\n", 376 | " def get_width(self):\n", 377 | " return self.__width\n", 378 | " def set_width(self, size):\n", 379 | " self.__width= size\n", 380 | " width=property(get_width,set_width)\n", 381 | " \n", 382 | " def get_height(self):\n", 383 | " return self.__height\n", 384 | " def set_height(self,size):\n", 385 | " self.__height=size\n", 386 | " height=property(get_height,set_height)\n", 387 | "\n", 388 | " def area(self):\n", 389 | " return self.width*self.height\n", 390 | " area=property(area)\n", 391 | " \n", 392 | "\n", 393 | " def perimeter(self):\n", 394 | " return (self.width+self.height)*2\n", 395 | " perimeter=property(perimeter)\n", 396 | "# 这样,就使用了property()函数包装出了width、height、area、perimeter四个特性\n", 397 | " \n", 398 | "rect=Rectangle(3,4)\n", 399 | "rect.width=5\n", 400 | "rect.height=6\n", 401 | "print(rect.width)\n", 402 | "print(rect.height)\n", 403 | "print(rect.area)\n", 404 | "print(rect.perimeter)" 405 | ] 406 | }, 407 | { 408 | "cell_type": "markdown", 409 | "metadata": {}, 410 | "source": [ 411 | "有了装饰器语法,以上代码可以简化为:" 412 | ] 413 | }, 414 | { 415 | "cell_type": "code", 416 | "execution_count": 25, 417 | "metadata": {}, 418 | "outputs": [ 419 | { 420 | "name": "stdout", 421 | "output_type": "stream", 422 | "text": [ 423 | "5\n", 424 | "6\n", 425 | "30\n", 426 | "22\n" 427 | ] 428 | } 429 | ], 430 | "source": [ 431 | "class Rectangle(object):\n", 432 | " def __init__ (self,width,height):\n", 433 | " self.__width = width\n", 434 | " self.__height = height\n", 435 | "\n", 436 | " @property\n", 437 | " def width(self):\n", 438 | " return self.__width\n", 439 | " \n", 440 | " @width.setter\n", 441 | " def width(self, size):\n", 442 | " self.__width= size\n", 443 | " \n", 444 | " @property\n", 445 | " def height(self):\n", 446 | " return self.__height\n", 447 | " \n", 448 | " @height.setter\n", 449 | " def height(self,size):\n", 450 | " self.__height=size\n", 451 | "\n", 452 | " @property\n", 453 | " def area(self):\n", 454 | " return self.width*self.height\n", 455 | " \n", 456 | " @property\n", 457 | " def perimeter(self):\n", 458 | " return (self.width+self.height)*2\n", 459 | "rect=Rectangle(3,4)\n", 460 | "rect.width=5\n", 461 | "rect.height=6\n", 462 | "print(rect.width)\n", 463 | "print(rect.height)\n", 464 | "print(rect.area)\n", 465 | "print(rect.perimeter)" 466 | ] 467 | }, 468 | { 469 | "cell_type": "markdown", 470 | "metadata": {}, 471 | "source": [ 472 | "#### 3.2 @staticmethod" 473 | ] 474 | }, 475 | { 476 | "cell_type": "markdown", 477 | "metadata": {}, 478 | "source": [ 479 | "将类中的方法修饰为静态方法,即类不需要创建实例的情况下,可以通过类名直接引用。到达将函数功能与实例解绑的效果。" 480 | ] 481 | }, 482 | { 483 | "cell_type": "code", 484 | "execution_count": 20, 485 | "metadata": {}, 486 | "outputs": [ 487 | { 488 | "name": "stdout", 489 | "output_type": "stream", 490 | "text": [ 491 | "通过实例引用方法\n", 492 | "5\n", 493 | "类名直接引用静态方法\n", 494 | "5\n" 495 | ] 496 | } 497 | ], 498 | "source": [ 499 | "class TestClass:\n", 500 | " name = 'test'\n", 501 | " def __init__(self,name):\n", 502 | " self.name = name\n", 503 | " \n", 504 | " @staticmethod\n", 505 | " def fun(self,x,y):\n", 506 | " return x+y\n", 507 | " \n", 508 | "cls = TestClass('Tom')\n", 509 | "print('通过实例引用方法')\n", 510 | "print(cls.fun(None,2,3)) # 参数个数必须与定义中的个数保持一致,否则报错\n", 511 | "print('类名直接引用静态方法')\n", 512 | "print(TestClass.fun(None,2,3)) # 参数个数必须与定义中的个数保持一致,否则报错" 513 | ] 514 | }, 515 | { 516 | "cell_type": "markdown", 517 | "metadata": {}, 518 | "source": [ 519 | "#### 3.3 @classmethod" 520 | ] 521 | }, 522 | { 523 | "cell_type": "markdown", 524 | "metadata": {}, 525 | "source": [ 526 | "类方法的第一个参数是一个类,是将类本身作为操作的方法。类方法被哪个类调用,就传入哪个类作为第一个参数进行操作。" 527 | ] 528 | }, 529 | { 530 | "cell_type": "code", 531 | "execution_count": 21, 532 | "metadata": {}, 533 | "outputs": [ 534 | { 535 | "name": "stdout", 536 | "output_type": "stream", 537 | "text": [ 538 | "通过实例调用\n", 539 | "Normal car of BMW\n", 540 | "通过类名直接调用\n", 541 | "SUV car of Benz\n" 542 | ] 543 | } 544 | ], 545 | "source": [ 546 | "class Car(object):\n", 547 | " car = 'audi'\n", 548 | " \n", 549 | " @classmethod\n", 550 | " def value(self,category): # 可定义多个参数,但第一个参数为类本身\n", 551 | " print('%s car of %s'%(category,self.car))\n", 552 | " \n", 553 | "class BMW(Car):\n", 554 | " car = 'BMW'\n", 555 | "\n", 556 | "class Benz(Car):\n", 557 | " car = 'Benz'\n", 558 | " \n", 559 | "print('通过实例调用')\n", 560 | "baoma = BMW()\n", 561 | "baoma.value('Normal')\n", 562 | "\n", 563 | "print('通过类名直接调用')\n", 564 | "Benz.value('SUV')" 565 | ] 566 | }, 567 | { 568 | "cell_type": "markdown", 569 | "metadata": {}, 570 | "source": [ 571 | "### 4. 装饰器链\n", 572 | "一个Python函数可以被多个装饰器修饰,若有多个装饰器时,它的执行顺序是从近到远依次执行。" 573 | ] 574 | }, 575 | { 576 | "cell_type": "code", 577 | "execution_count": 21, 578 | "metadata": {}, 579 | "outputs": [ 580 | { 581 | "name": "stdout", 582 | "output_type": "stream", 583 | "text": [ 584 | "Hello\n" 585 | ] 586 | } 587 | ], 588 | "source": [ 589 | "def makebold(f):\n", 590 | " return lambda: '' + f() + ''\n", 591 | "\n", 592 | "def makeitalic(f):\n", 593 | " return lambda: '' + f() + ''\n", 594 | "\n", 595 | "@makebold\n", 596 | "@makeitalic\n", 597 | "def say():\n", 598 | " return 'Hello'\n", 599 | "\n", 600 | "print(say()) " 601 | ] 602 | }, 603 | { 604 | "cell_type": "markdown", 605 | "metadata": {}, 606 | "source": [ 607 | "### 5. 需要注意的地方" 608 | ] 609 | }, 610 | { 611 | "cell_type": "markdown", 612 | "metadata": {}, 613 | "source": [ 614 | "#### 5.1 用functools.wraps装饰内层函数" 615 | ] 616 | }, 617 | { 618 | "cell_type": "markdown", 619 | "metadata": {}, 620 | "source": [ 621 | "使用装饰器极大地复用了代码,但是他有一个缺点就是原函数的元信息不见了,比如函数的docstring、\\__name\\__、参数列表,如下面例子所示:" 622 | ] 623 | }, 624 | { 625 | "cell_type": "code", 626 | "execution_count": 27, 627 | "metadata": {}, 628 | "outputs": [ 629 | { 630 | "data": { 631 | "text/plain": [ 632 | ".with_logging>" 633 | ] 634 | }, 635 | "execution_count": 27, 636 | "metadata": {}, 637 | "output_type": "execute_result" 638 | } 639 | ], 640 | "source": [ 641 | "# 装饰器\n", 642 | "def logged(func):\n", 643 | " def with_logging(*args, **kwargs):\n", 644 | " print(func.__name__) # 输出 'with_logging'\n", 645 | " print(func.__doc__) # 输出 None\n", 646 | " return func(*args, **kwargs)\n", 647 | " return with_logging\n", 648 | "\n", 649 | "# 函数\n", 650 | "@logged\n", 651 | "def f(x):\n", 652 | " \"\"\"does some math\"\"\"\n", 653 | " return x + x * x\n", 654 | "\n", 655 | "logged(f)" 656 | ] 657 | }, 658 | { 659 | "cell_type": "markdown", 660 | "metadata": {}, 661 | "source": [ 662 | "不难发现,函数 f 被with_logging取代了,当然它的docstring,\\__name\\__就是变成了with_logging函数的信息了。好在我们有functools.wraps,wraps本身也是一个装饰器,它能把原函数的元信息拷贝到装饰器里面的 func 函数中,这使得装饰器里面的 func 函数也有和原函数 foo 一样的元信息了。" 663 | ] 664 | }, 665 | { 666 | "cell_type": "code", 667 | "execution_count": 28, 668 | "metadata": {}, 669 | "outputs": [ 670 | { 671 | "data": { 672 | "text/plain": [ 673 | "" 674 | ] 675 | }, 676 | "execution_count": 28, 677 | "metadata": {}, 678 | "output_type": "execute_result" 679 | } 680 | ], 681 | "source": [ 682 | "from functools import wraps\n", 683 | "def logged(func):\n", 684 | " @wraps(func)\n", 685 | " def with_logging(*args, **kwargs):\n", 686 | " print(func.__name__) # 输出 'f'\n", 687 | " print(func.__doc__) \n", 688 | " return func(*args, **kwargs)\n", 689 | " return with_logging\n", 690 | "\n", 691 | "@logged\n", 692 | "def f(x):\n", 693 | " \"\"\"does some math\"\"\"\n", 694 | " return x + x * x\n", 695 | "logged(f)" 696 | ] 697 | }, 698 | { 699 | "cell_type": "markdown", 700 | "metadata": {}, 701 | "source": [ 702 | "#### 5.2 修改外层变量时记得使用nonlocal" 703 | ] 704 | }, 705 | { 706 | "cell_type": "markdown", 707 | "metadata": {}, 708 | "source": [ 709 | "装饰器是对函数对象的一个高级应用。在编写装饰器的过程中,你会经常碰到内层函数需要修改外层函数变量的情况。就像下面这个装饰器一样:" 710 | ] 711 | }, 712 | { 713 | "cell_type": "code", 714 | "execution_count": 29, 715 | "metadata": {}, 716 | "outputs": [ 717 | { 718 | "ename": "UnboundLocalError", 719 | "evalue": "local variable 'count' referenced before assignment", 720 | "output_type": "error", 721 | "traceback": [ 722 | "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", 723 | "\u001b[1;31mUnboundLocalError\u001b[0m Traceback (most recent call last)", 724 | "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[0;32m 15\u001b[0m \u001b[1;32mdef\u001b[0m \u001b[0mfoo\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 16\u001b[0m \u001b[1;32mpass\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 17\u001b[1;33m \u001b[0mfoo\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", 725 | "\u001b[1;32m\u001b[0m in \u001b[0;36mdecorated\u001b[1;34m(*args, **kwargs)\u001b[0m\n\u001b[0;32m 7\u001b[0m \u001b[1;32mdef\u001b[0m \u001b[0mdecorated\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m*\u001b[0m\u001b[0margs\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 8\u001b[0m \u001b[1;31m# 次数累加\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 9\u001b[1;33m \u001b[0mcount\u001b[0m \u001b[1;33m+=\u001b[0m \u001b[1;36m1\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 10\u001b[0m \u001b[0mprint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34mf\"Count:{count}\"\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 11\u001b[0m \u001b[1;32mreturn\u001b[0m \u001b[0mfunc\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m*\u001b[0m\u001b[0margs\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", 726 | "\u001b[1;31mUnboundLocalError\u001b[0m: local variable 'count' referenced before assignment" 727 | ] 728 | } 729 | ], 730 | "source": [ 731 | "import functools\n", 732 | "\n", 733 | "def counter(func):\n", 734 | " \"\"\"装饰器:记录并打印调用次数\"\"\"\n", 735 | " count = 0\n", 736 | " @functools.wraps(func)\n", 737 | " def decorated(*args,**kwargs):\n", 738 | " # 次数累加\n", 739 | " count += 1\n", 740 | " print(f\"Count:{count}\")\n", 741 | " return func(*args,**kwargs)\n", 742 | " return decorated\n", 743 | "\n", 744 | "@counter\n", 745 | "def foo():\n", 746 | " pass\n", 747 | "foo()" 748 | ] 749 | }, 750 | { 751 | "cell_type": "markdown", 752 | "metadata": {}, 753 | "source": [ 754 | "为了统计函数调用次数,我们需要在 decorated 函数内部修改外层函数定义的 count 变量的值。但是,上面这段代码是有问题的,在执行它时解释器会报错。" 755 | ] 756 | }, 757 | { 758 | "cell_type": "markdown", 759 | "metadata": {}, 760 | "source": [ 761 | "这个错误是由 counter 与 decorated 函数互相嵌套的作用域引起的。当解释器执行到 count+=1 时,并不知道 count 是一个在外层作用域定义的变量,它把 count 当做一个局部变量,并在当前作用域内查找。最终却没有找到有关 count 变量的任何定义,然后抛出错误。" 762 | ] 763 | }, 764 | { 765 | "cell_type": "markdown", 766 | "metadata": {}, 767 | "source": [ 768 | "为了解决这个问题,我们需要通过 nonlocal 关键字告诉解释器:“count 变量并不属于当前的 local 作用域,去外面找找吧”,之前的错误就可以得到解决。" 769 | ] 770 | }, 771 | { 772 | "cell_type": "code", 773 | "execution_count": 31, 774 | "metadata": {}, 775 | "outputs": [ 776 | { 777 | "name": "stdout", 778 | "output_type": "stream", 779 | "text": [ 780 | "Count:1\n" 781 | ] 782 | } 783 | ], 784 | "source": [ 785 | "import functools\n", 786 | "\n", 787 | "def counter(func):\n", 788 | " \"\"\"装饰器:记录并打印调用次数\"\"\"\n", 789 | " count = 0\n", 790 | " @functools.wraps(func)\n", 791 | " def decorated(*args,**kwargs):\n", 792 | " # 次数累加\n", 793 | " nonlocal count\n", 794 | " count += 1\n", 795 | " print(f\"Count:{count}\")\n", 796 | " return func(*args,**kwargs)\n", 797 | " return decorated\n", 798 | "\n", 799 | "@counter\n", 800 | "def foo():\n", 801 | " pass\n", 802 | "foo()" 803 | ] 804 | }, 805 | { 806 | "cell_type": "code", 807 | "execution_count": null, 808 | "metadata": { 809 | "collapsed": true 810 | }, 811 | "outputs": [], 812 | "source": [] 813 | } 814 | ], 815 | "metadata": { 816 | "kernelspec": { 817 | "display_name": "Python 3", 818 | "language": "python", 819 | "name": "python3" 820 | }, 821 | "language_info": { 822 | "codemirror_mode": { 823 | "name": "ipython", 824 | "version": 3 825 | }, 826 | "file_extension": ".py", 827 | "mimetype": "text/x-python", 828 | "name": "python", 829 | "nbconvert_exporter": "python", 830 | "pygments_lexer": "ipython3", 831 | "version": "3.6.1" 832 | }, 833 | "varInspector": { 834 | "cols": { 835 | "lenName": 16, 836 | "lenType": 16, 837 | "lenVar": 40 838 | }, 839 | "kernels_config": { 840 | "python": { 841 | "delete_cmd_postfix": "", 842 | "delete_cmd_prefix": "del ", 843 | "library": "var_list.py", 844 | "varRefreshCmd": "print(var_dic_list())" 845 | }, 846 | "r": { 847 | "delete_cmd_postfix": ") ", 848 | "delete_cmd_prefix": "rm(", 849 | "library": "var_list.r", 850 | "varRefreshCmd": "cat(var_dic_list()) " 851 | } 852 | }, 853 | "types_to_exclude": [ 854 | "module", 855 | "function", 856 | "builtin_function_or_method", 857 | "instance", 858 | "_Feature" 859 | ], 860 | "window_display": false 861 | } 862 | }, 863 | "nbformat": 4, 864 | "nbformat_minor": 2 865 | } 866 | -------------------------------------------------------------------------------- /8 Python 装饰器.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetalkdata/python_script-manual/4720aec496fe9b6f2b5e5fa92cf6aace864aac82/8 Python 装饰器.pdf -------------------------------------------------------------------------------- /9 绘图可视化部分.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetalkdata/python_script-manual/4720aec496fe9b6f2b5e5fa92cf6aace864aac82/9 绘图可视化部分.pdf -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # python-工具代码速查手册 2 | 这个项目是python的工具代码,速查手册。使用notebook把常用的代码和说明进行总结,供大家快速查看使用。 3 | --------------------------------------------------------------------------------