├── doc ├── mybatis │ └── README.md ├── linux │ └── README.md ├── docker │ └── README.md ├── elasticsearch │ └── README.md ├── wx │ ├── login │ │ └── README.md │ └── card │ │ └── README.md ├── github │ └── README.md ├── django │ └── README.md ├── hadoop │ └── README.md └── python │ └── README.md ├── learning-github.iml ├── .gitattributes ├── .gitignore └── README.md /doc/mybatis/README.md: -------------------------------------------------------------------------------- 1 | # MyBatis - 学习笔记 2 | -------------------------------------------------------------------------------- /learning-github.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /doc/linux/README.md: -------------------------------------------------------------------------------- 1 | # Linux 基础 - 学习笔记 2 | ## 1. 文件系统中跳转 3 | 4 | ### 1.1 文件系统树 5 | >Linux 总是只有一个单一的文件系统树,不管有多少个磁盘或者存储设备连接到计算机上。 根据负责维护系统安全的系统管理员的兴致,存储设备连接到(或着更精确些,是挂载到)目录树的各个节点上。 6 | 7 | - 当前工作目录`pwd`; 8 | - 列出目录内容`ls`; 9 | - 更改当前工作目录`cd`; 10 | - 绝对路径/相对路径; 11 | 12 | ### 1.2 cd命令 13 | - `cd`:无参数,返回用户主目录; 14 | - `cd -`:更改工作目录到先前的工作目录。; 15 | - `cd ~user_name`:更改工作目录到用户家目录。例如, cd ~bob 会更改工作目录到用户“bob”的家目录 16 | 17 | ### 1.3 文件名的重要规则 18 | - 以`.` 字符开头的文件名是隐藏文件。这仅表示,`ls` 命令不能列出它们, 用 `ls -a` 命令就可以了; 19 | - 文件名和命令名是大小写敏感的; 20 | - `Linux` 没有文件扩展名的概念; 21 | - 文件名中标点符号仅限 使用`.`,`_`,`-`。最重要的是,不要在文件名中使用空格; 22 | 23 | ## 1. 操作文件和目录 24 | -------------------------------------------------------------------------------- /doc/docker/README.md: -------------------------------------------------------------------------------- 1 | # Docker - 学习笔记 2 | 3 | ## 1. Docker简介 4 | - Docker是容器管理工具; 5 | - 解决问题: 6 | - 快速创建环境; 7 | - 整体交付; 8 | - 环境一致性保证; 9 | - 更好的完成devops; 10 | 11 | ## 2. Docker安装 12 | - 使用`uname -r`检查Linux的内核版本,需要大于`3.10`; 13 | - 安装`curl`程序; 14 | - 使用`curl -sSL https://get.docker.com/ | sh`命令安装docker; 15 | - 使用`docker -v`检查版本; 16 | - 使用`systemctl start docker`启动docker服务; 17 | - 使用`systemctl enable docker`设置为开机启动; 18 | - 使用`ps -aux | grep docker`检查`docker`容器的运行情况; 19 | 20 | ## 3. Docker镜像 21 | - Docker镜像:即为**把业务代码和运行环境进行整体打包**; 22 | - 基础的Docker镜像:从公共仓库直接拉取,由原厂进行维护; 23 | - 定制镜像:编写dockerfile,重新编译打包成镜像,是推荐的使用方式; 24 | - Commit镜像:通过镜像启动容器,通过commit命令形成镜像; 25 | 26 | ### 3.1 镜像分层技术 27 | - `AUFS(Another Union File System)`即为镜像分层技术,支持将多个目录挂载到同一个虚拟目录下; 28 | - 镜像分为多个`layer`,每个`layer`ID和大小; 29 | - 已构建的镜像会设置成只读模式,`read-write`写操作实在`read-only`上的一种增量操作,故不会影响`read-only`层; 30 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows image file caches 2 | Thumbs.db 3 | ehthumbs.db 4 | 5 | # Folder config file 6 | Desktop.ini 7 | 8 | # Recycle Bin used on file shares 9 | $RECYCLE.BIN/ 10 | 11 | # Windows Installer files 12 | *.cab 13 | *.msi 14 | *.msm 15 | *.msp 16 | 17 | # Windows shortcuts 18 | *.lnk 19 | 20 | # ========================= 21 | # Operating System Files 22 | # ========================= 23 | 24 | # OSX 25 | # ========================= 26 | 27 | .DS_Store 28 | .AppleDouble 29 | .LSOverride 30 | 31 | # Thumbnails 32 | ._* 33 | 34 | # Files that might appear in the root of a volume 35 | .DocumentRevisions-V100 36 | .fseventsd 37 | .Spotlight-V100 38 | .TemporaryItems 39 | .Trashes 40 | .VolumeIcon.icns 41 | 42 | # Directories potentially created on remote AFP share 43 | .AppleDB 44 | .AppleDesktop 45 | Network Trash Folder 46 | Temporary Items 47 | .apdisk 48 | -------------------------------------------------------------------------------- /doc/elasticsearch/README.md: -------------------------------------------------------------------------------- 1 | # Elasticsearch - 学习笔记 2 | ## 1. 简介 3 | > `Elasticsearch` 是一个高度可伸缩的开源全文检索和分析引擎。它使你能够存储、查询、搜索、分析大量的数据,并且能够几乎实时的查询。通常被用实现应用程序复杂检索要求的底层技术引擎。 4 | 5 | `Elasticsearch`可以用于以下场景: 6 | - 在线购物商城; 7 | - 海量日志分析平台; 8 | - 商品价格预警; 9 | - 商业智能分析; 10 | 11 | ## 1.1 基本概念 12 | 13 | ### 1.1.1 Cluster - 集群 14 | 15 | ### 1.1.2 Node - 集群 16 | 17 | ### 1.2.3 Index - 索引 18 | 19 | ### 1.2.4 Type - 类型 20 | 21 | ### 1.2.5 Document - 文档 22 | 23 | ### 1.2.6 Shards & Replicas - 分片和副本 24 | 25 | ## 1.2 安装Elasticsearch 26 | 27 | ## 1.3 探索集群 28 | 29 | ### 1.3.1 查询集群健康状态 30 | 31 | ### 1.3.2 列出索引 32 | 33 | ### 1.3.3 创建索引 34 | 35 | ### 1.3.1 索引并查询文档 36 | 37 | ### 1.3.1 删除索引 38 | 39 | ## 1.4 修改数据 40 | 41 | ### 1.4.1 更新文档 42 | 43 | ### 1.4.2 删除文档 44 | 45 | ### 1.4.3 批量处理 46 | 47 | ## 1.5 查询数据 48 | 49 | ### 1.5.1 搜索API 50 | 51 | ### 1.5.2 查询语言 52 | 53 | ### 1.5.3 执行查询 54 | 55 | ### 1.5.4 查询过滤器 56 | 57 | ### 1.5.5 聚合查询 -------------------------------------------------------------------------------- /doc/wx/login/README.md: -------------------------------------------------------------------------------- 1 | # 微信授权登录 - 学习笔记 2 | 3 | ## 1. 登录方式 4 | - 微信开放平台:PC端二维码扫描; 5 | - 微信公众号:手机端弹出微信授权页面; 6 | 7 | ## 2. 实现方式 8 | - 没有自己的账号体系:直接拉取微信用户信息来进行网站 9 | - 有自己的账号体系:授权成功后需要绑定自己的账号;需要绑定微信`openid`了; 10 | 11 | ## 3. OAuth 2.0 协议 12 | ### 3.1 简介 13 | - OAuth:Open Authorization 开放式授权协议; 14 | - OAuth:为用户资源的授权提供了一个安全、开放、简易的标准;不会使第三方接触到用户的账号信息; 15 | 16 | ###3.2 原理 17 | ![原理图](./1491916594616.png) 18 | 19 | ### 3.3 版本 20 | - `OAuth 1.0`:发布于2007年,有较为严重的漏洞; 21 | - `OAuth 2.0`:发布与2010年,被大型企业广泛使用; 22 | 23 | ### 3.4 场景 24 | - 授权登录; 25 | - 符合授权规则的情况下访问各种API; 26 | - 公司内部的资源开放; 27 | 28 | ### 3.5 步骤 29 | **步骤一:请求OAuth登录页** 30 | - `Request Token URL` :未授权的令牌请求地址;未授权时请求带有特定参数的URL; 31 | - `app_id`:每一个唯一的客户端都有一个APP_ID; 32 | - `redirect_uri`:客户端回调地址; 33 | 34 | **步骤二:用户使用QQ号登录并授权** 35 | - `redirect_uri`:用户登录成功后会跳转的地址; 36 | - `code`:请求成功后返回的结果; 37 | 38 | **步骤三:返回登录结果** 39 | - `User Authorization URL`:用户授权的令牌请求服务地址;授权之后需要请求带有参数的URL; 40 | - `app_id`:客户端账号; 41 | - `app_key`:客户端密码; 42 | - `code`:授权登录后的结果;在规定时间范围内(很短),只可以使用一次的字符串; 43 | - `AccessToken`:用户通过第三方应用访问OAuth接口的令牌;具有较长的生命周期; 44 | - `RefreshToken`:获取新的令牌; -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 学习计划 2 | 3 | ## 微信开放平台 4 | > [微信授权登录](https://github.com/coolhwm/learning-index/tree/master/doc/wx/login) 5 | 6 | > [微信卡券](https://github.com/coolhwm/learning-index/tree/master/doc/wx/card) 7 | 8 | 9 | ## 前端技术 10 | 11 | > [目录-前端技术学习笔记](https://github.com/coolhwm/learning-front-end-dev) 12 | 13 | ## Java 14 | 15 | > [目录-Java技术学习笔记](https://github.com/coolhwm/learning-java) 16 | 17 | ## MyBatis 18 | > [目录-MyBatis学习笔记](https://github.com/coolhwm/learning-mybatis) 19 | 20 | ## Hadoop 21 | > [Hadoop 学习笔记](https://github.com/coolhwm/learning-index/tree/master/doc/hadoop) 22 | 23 | ## Elasticsearch 24 | > [Elasticsearch 学习笔记](https://github.com/coolhwm/learning-index/tree/master/doc/elasticsearch) 25 | 26 | ## Python 27 | > [Python 学习笔记](https://github.com/coolhwm/learning-index/tree/master/doc/python) 28 | 29 | ## Docker 30 | > [Docker 学习笔记](https://github.com/coolhwm/learning-index/tree/master/doc/docker) 31 | 32 | ## Django 33 | 34 | > [Django 学习笔记](https://github.com/coolhwm/learning-index/tree/master/doc/django) 35 | 36 | ## Github 37 | > [Github 学习笔记](https://github.com/coolhwm/learning-index/tree/master/doc/github) 38 | 39 | -------------------------------------------------------------------------------- /doc/github/README.md: -------------------------------------------------------------------------------- 1 | # Github - 学习笔记 2 | ## 基本概念 3 | ### commit 版本 4 | * 基本概念:做一个版本(动词)、一个版本(名词); 5 | * 内容:操作人、操作时间、操作内容、描述信息(版本留言); 6 | 7 | ### 版本号 8 | * 构成:40位的UUID,随机、不分先后顺序; 9 | * 原理:保存了自己的版本号及父版本号(7位,简写形式),可以形成所有的版本历史线; 10 | * 访问:利用版本号及简写,可以直接通过URL访问版本的页面; 11 | 12 | ### branch 分支 13 | * master分支:master分支类似一个指针,指向最新的版本,主分支的内容确保是可部署的;一个仓库可以不止一个分支; 14 | * 创建分支:可以选取一个分支(默认为master),创建一个新的分支;创建分支时没有创建文件拷贝,只是创建了一个新的指针; 15 | * 切换分支:切换分支时,本地文件的版本也会随之切换; 16 | * 发布分支:将分支发布到github上; 17 | * 删除分支:可以在github网页上删除分支; 18 | * 默认分支:可以在github网页更改默认分支; 19 | 20 | ## 分支合并 21 | * 合并分支(merge):会创建一个融合版本,融合版本有两个父版本,起到链接两个分支的作用(融合); 22 | 23 | 24 | * 远端与本地合并(rebase):修改尚未提交时,服务端内容已被修改,也可以使用同步功能合并(变基); 25 | 26 | ## 冲突 27 | * 本地未提交,同步远端:无法同步,会提示本地未提交的内容将被覆盖; 28 | * 本地已提交,同步远端:发生冲突,冲突的文件生成冲突标识符;需要删除冲突标识符及冲突代码,在提交新的版本; 29 | 30 | ## 团队协作 31 | * 添加协作者:在项目设置中,可以添加Collaborators,协作者和所有者拥有同样的写权限; 32 | * 创建新分支:新分支上所做的修改不会影响到主(master) 分支,可以自由实验和提交修改,在审核之前,分支内容是不会被合并; 33 | * 添加新版本:在分支中进行开发,可以提交的版本; 34 | * 发布Pull request:拉取请求,请求作者将分支内容拉取到主版本上;需要保证所有内容都同步到远端; 35 | * 讨论和代码审核:可以在提交版本上发表评论(comment); 36 | * 更新版本:在Pull request期间,如果要更新版本,无需撤销Pull request,只需要再次提交版本即可; 37 | * 接受Pull request:分支的内容会被合并到指定的基线版本; 38 | * 删除分支:合并后的分支一般没有用了,可以直接删除; 39 | 40 | ## 贡献开源项目 41 | * Fork:在自己的名下创建拷贝; 42 | * 在Fork中修改并提交版本; 43 | * Pull Request:发起拉取请求;在网页上可以用快速Pull request; 44 | * 等待参与者审核; 45 | * 删除Fork; 46 | 47 | ## Issues 事务卡片 48 | * 用于讨论项目各种事务; 49 | * 分配(assign):可以将事务分配给参与者; 50 | * 评论(comment):可以参与讨论,可以回复他人,可以使用markdown语法; 51 | * Pull requets:也是一个Issues,是由代码引发的讨论; 52 | * 提交标签:# 关联事务; fix # 关闭事务; -------------------------------------------------------------------------------- /doc/wx/card/README.md: -------------------------------------------------------------------------------- 1 | # 【资料】卡券使用规则解读与摘要 2 | 3 | # 官方文档汇总 4 | - [公众平台开发者文档](https://mp.weixin.qq.com/wiki/home/index.html) 5 | - [公众平台技术文档](https://mp.weixin.qq.com/wiki) 6 | - [微信卡券相关文档](https://mp.weixin.qq.com/cgi-bin/readtemplate?t=cardticket/faq_tmpl&type=info&lang=zh_CN) 7 | - [微信卡券第三方代制指引文档](https://mp.weixin.qq.com/cgi-bin/announce?action=getannouncement&key=1459357007&version=1&lang=zh_CN&platform=2) 8 | - [第三方代制功能概况](http://kf.qq.com/faq/120911VrYVrA150928YB7FN3.html) 9 | - [第三方平台概述](https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419318292&token=&lang=zh_CN) 10 | - [卡券小程序打通](https://mp.weixin.qq.com/cgi-bin/announce?action=getannouncement&key=1490190158&version=1&lang=zh_CN&platform=2) 11 | 12 | 13 | # 一、微信卡券使用规则 14 | 15 | ## 1. 功能介绍 16 | - **功能**:电子卡券生成、下发、领取、核销的闭环,并使用对账、卡券管理等配套功能; 17 | - **方式**:API接口功能(需要开发)、公众平台卡券功能; 18 | 19 | ## 2. 开放范围 20 | 21 | ### 2.1 开放类目 22 | 开放类目有一定限制: 23 | - 美食; 24 | - 休闲娱乐; 25 | - 生活服务; 26 | - 运输票务; 27 | - 电影票; 28 | - 旅游; 29 | - 酒店; 30 | - 购物; 31 | - 虚拟; 32 | 33 | ### 2.2 开放制卷模式 34 | - **自主制券**:有公众号与资质、公众平台操作、数据属于公众号、卡券类型无限制; 35 | - **第三方代制**:无资质、接口制券、数据属于开发者账号、可制作普通券; 36 | 37 | ### 2.3 开放卷类型 38 | - **普通券**:代金券、折扣券、兑换券、团购券、优惠券; 39 | - **特殊券**:电影票、飞机票等; 40 | 41 | ## 3. 卡券功能开通指引 42 | 43 | ### 3.1 申请渠道 44 | - **公众平台(API)**:创建、投放、管理、核销、对账;不支持会员卡和特殊卷; 45 | - **公众平台(免开发)**:创建、投放、管理、核销、对账; 46 | - **开放平台**:能够在第三方应用加入微信卡包; 47 | 48 | ### 3.2 申请条件 49 | - **公众平台** 50 | - 账号已认证; 51 | - 无认证、公众号,可以使用第三方开发者代制; 52 | - **开放平台** 53 | - 移动平台已通过审核; 54 | - 移动应用主体通过开发者认证; 55 | - 运营内容合法; 56 | 57 | ##4. 制卷审核规则 58 | - **快速通道**:先投放、后抽查;商户不能有违规行为; 59 | - **普通通道**:先审核(1工作日),后投放; 60 | 61 | ## 5. 违规处理措施 62 | - **制券违规**:商品和服务不是散户提供的; 63 | - **投诉违规**:无法兑换或无法使用; 64 | 65 | *处理标准“:根据投诉次数,给予不同力度的处理* 66 | 67 | ## 6. 自主制卷模式使用规则 68 | - **模式介绍**:为品牌散户、自营商品服务的线下商户、线上品牌电商提供发放优惠券功能; 69 | - **开放范围**:同上; 70 | - **申请流程**:公众号接入、开通卡券权限、审核注册门店、创建卡券、制卷审核、发卷领券、核销; 71 | - **审核标准**:服务清晰、品牌与主体一致;兑换内容为公众号直接提供; 72 | - **违规处理**:警告、下架卡券、关闭快速审核、关闭制卷、关闭领取、关闭卡券; 73 | 74 | ## 7. 第三方代制模式使用规则 75 | > 让有运营能力或技术能力的第三方,基于微信公众平台,为有卡券需求的合作商户(下文中简称“**子商户**”)提供卡券功能接入、使用及完整的营销闭环解决方案 76 | 77 | > 开通了卡券功能的第三方公众号,经合作商户授权并**报备资质**、资料后,可通过公众平台或**API接口**实现代制功能 78 | 79 | **规则要点** 80 | - 子商户本身不需要微信公众号或相关资质; 81 | - 第三方代制公众号,报备资质后可以通过API接口实现代制功能; 82 | - 卡券商品和服务均由子商户提供,卡券先知子商户的商户名和LOGO; 83 | - 子商户只能通过第三方的公众号代为完成; 84 | - 子商户本身不具备直接调用卡券接口或后台操作的能力; 85 | 86 | ## 8. 第三方强授权模式使用规则 87 | 88 | > 微信第三方平台大全:http://3p.weixingate.com/ 89 | 90 | > 微信开放平台针对“公众号第三方平台”账号类型推出“卡券第三方强授权”功能.具备开发能力的开发者,可协助未认证公众号商户快速接入并使用卡券功能。 91 | 92 | **规则要点** 93 | - 审核时公众号第三方平台需提供相关资质; 94 | - 子商户为未开通卡券功能的微信公众号,由第三方代为提交相关资质; 95 | - -子商户本身不具备直接调用卡券接口的能力; 96 | 97 | 98 | ## 附1. 快速申请卡券功能 99 | - 登录微信平台,开通卡券功能 100 | - 填写申请资料、正确选择类目、清晰描述商品、提交资质文件; 101 | - 等待审核通过、创建门店; 102 | - 申请开通高级权限(储值); 103 | - 等待制卷信息审核、快速通道、投放卡卷; 104 | 105 | # 二、朋友共享的优惠券使用规则 106 | 107 | ## 1. 功能简介 108 | - **自动共享**:领取并与朋友共享此卷,卷会自动展示在领取人及其朋友的优惠券的列表中; 109 | - **持续共享**:朋友的卷被已使用时,商家可以配置立即再次赠送一张朋友的卷,实现持续共享; 110 | - **支持范围**:代金券、兑换券(仅支持接口); 111 | 112 | ## 2. 开放范围 113 | - **逐步开放**:目前仅部分类目开放朋友的卷; 114 | - **第三方开发者代制**:默认开通朋友的卷; 115 | 116 | ## 3. 申请指引 117 | - **无需申请**:符合开放范围的商户自动开放; 118 | - **开通卡券**:只需要开通卡券功能即可; 119 | 120 | ## 4. 收费标准 121 | - **库存单价**:无门槛0.2卷点/张、有门槛0.4卷点/张; 122 | - **付费充值**:可以在后台模块进行付费购买,1元=1卷点; 123 | - **平台活动**:平台不定期赠送卷点; 124 | - **消耗机制**:按领卷进行字段,分享的不计算; 125 | - **库存退回**:未领取退回卷点,不支持退款; 126 | 127 | ## 5. 投放方式 128 | - **仅支持线下**:扫码、摇一摇、WIFI、不支持公众号; 129 | 130 | ## 6. 审核标准 131 | - **卡券类型**:仅支持兑换券和代金卷; 132 | - **无门槛卷**:全场通用、无低消、无需预约; 133 | 134 | ## 7. 违规处理 135 | - **违规行为**:虚假门店、大量投诉、恶意核销、无实际优惠、恶意刷量; 136 | - **处理方法**:下架卡券、终止共享、关闭使用、关闭朋友的卷、暂停建立、扣除奖励平; 137 | 138 | 139 | # 三、会员卡商户使用规则 140 | 141 | ## 1. 功能介绍 142 | > 微信新版会员卡,着重打造线下开卡场景,包含开卡激活、积分查询、快速买单、积分使用等功能 143 | 144 | ## 2. 开放范围 145 | - **范围限制**:目前仅向部分类目开放; 146 | - **第三方开发者代制**:当子商户符合开放类目时,可以代子商户制会员卡; 147 | 148 | ## 3. 申请指引 149 | - **基础权限**:申请开通卡卷功能后,同时获得会员卡权限,无需另行申请; 150 | - **特殊权限**:重置功能需要申请备案后开放; 151 | 152 | ## 4. 审核规则 153 | - **审核规则**:快速审核通道,10分钟内生效; 154 | - **违规处理**:补交授权、暂停领取、暂停制卡; 155 | 156 | # 四、卡卷商户后台文档 157 | 158 | ## 1. 功能介绍 159 | > 卡券功能,是公众平台向有投放卡券需求的公众号提供的管理、推广、经营分析的整套解决方案。商户可通过卡券功能,实现卡券的管理与运营。 160 | 161 | - **投放渠道:** 162 | - 自定义菜单; 163 | - 卡券消息(直接消息、嵌入图文消息、自动回复消息); 164 | - 扫描二维码; 165 | - **运营方式:** 166 | - 推荐关注:通过卡卷诱导关注发圈的公众号: 167 | - 赠送好友:可以转增; 168 | - 适用门店:可以帮助快速定位到店; 169 | - **支撑服务:** 170 | - 数据分析; 171 | - 多种方式核销; 172 | - API接口管理卡券数据; 173 | 174 | ## 2. 卡券管理 175 | - **管理页面**:生成、查看、编辑、删除、投放、报表; 176 | - **卡券状态**:审核中、未通过、待投放、已投放、已过期; 177 | - **卡券生成**: 178 | - 类型:折扣券、兑换券、团购卷、优惠券; 179 | - 门店:介意关联门店; 180 | - 信息:通用信息、专有信息; 181 | - **卡券投放**:群发、图文消息、下载二维码、自动回复; 182 | 183 | ## 3. 卡券核销 184 | ### 3.3 商户核销 185 | - **手机核销**:核销员、门店、使用卡券商户助手公众号; 186 | - **网页核销**:登录网站,输入卡券号; 187 | 188 | ### 3.1 自助核销 189 | - **卡券配置**:卡券选择为自助核销即可设置; 190 | - **使用场景**:自助核销有用户发起,全程由客户进行操作,适合对账需求不强的商户; 191 | 192 | ## 4. 微信买单 193 | ### 4.1 功能简介 194 | > 微信买单是微信卡券的一项能力,消费者到店结账时,通过使用微信买单,拉起微信支付快速完成付款,且系统会自动使用优惠。 195 | 196 | - **自动优惠**:使用微信买单结账,会自动使用优惠; 197 | - **无需开发**:款项自动打入微信支付账号; 198 | - **付款通知**:通过卡券助手公众号收到收款消息; 199 | - **支持卡券**: 自动使用优惠券、买单反积分、积分抵现; 200 | 201 | ### 4.2 商户后台操作 202 | - **申请开通权限**:申请微信买单,绑定核销员,选择门店; 203 | - **设置卡券**:卡券设置为微信买单,设置为有核销员的门店; 204 | - **设置会员卡**:会员卡设置为积分抵扣,并设置为支持微信买单; 205 | - **卡券核销**:添加核销员、关注卡券商户助手; 206 | 207 | ## 5. 会员卡 208 | ### 5.1 功能定位 209 | - **基本功能**:线上开卡、快速买单、积分使用; 210 | - **经营能力**:二维码领取、卡片功能、快速买单、数据与对账; 211 | 212 | ### 5.2 开放范围 213 | - **开放类目**:部门符合类目的卡券商家; 214 | - **第三方代制**:可以为符合类目的子商户,通过API接口代制会员卡; 215 | 216 | ### 5.3 会员卡管理 217 | - **会员卡审核**:卡券商户后台只能创建一张会员卡;审核即时生效; 218 | - **会员卡创建**:后台创建为所见即所得方式; 219 | - 会员卡优惠:提供这就优惠和积分优惠两种优惠工具; 220 | - 微信买单:可以和买单功能组合使用形成营销手段; 221 | - 自定义入口:自定义入口可以配置图文消息、卡券货架、小店货架、网页链接等; 222 | - 会员卡激活:可以收集到客户的手机号等信息; 223 | - **会员管理**:可以在会员管理中查看并管理会员信息; 224 | - 分组:会员可以进行分组; 225 | - 检索:可以通过会员卡号、收集、姓名等信息进行搜索; 226 | - 状态:有效、未激活、失效; 227 | - **会员卡消息**:可以先会员定向发送消息; 228 | - 消息限额:限额计入公众平台消息; 229 | - 积分变动送券:积分变动后通知的消息,可以同时送出一张优惠券; 230 | **会员卡数据**:可以查看会员卡的运营数据; 231 | **会员卡使用**:与卡券使用相同; 232 | - 卡券商户助手:直接扫描、手机号搜索; 233 | - 微信买单:核销方式为微信买单、关联有核销员的门店、店员关注助手接受通知; 234 | - **二维码投放**:二维码可以放置到线下店铺; 235 | - 领卡激活:直接扫码领卡并激活; 236 | - 微信买单:已经领卡的会员,扫码可以自己进行微信买单; 237 | 238 | ## 6. 朋友的卷 239 | 240 | - **功能简介**:基于微信优惠券推出的新功能,实现“一人领取多人共享”的快速社交传播和转化的效果; 241 | - **优势**:高曝光量、高转化率、朋友推荐、裂变; 242 | - **类型**:有门槛、无门槛,二者收费不同; 243 | - **开通**:符合开放类目的散户都可以开通; 244 | - **卷点**:朋友的券有库存定价,有门槛0.4卷点/张,无没看0.2卷点/张; 245 | - 基于微信优惠券推出的新功能,实现“一人领取多人共享”的快速社交传播和转化的效果 246 | - **创建**:和普通券类似,不支持商户自定义code类型; 247 | - **投放**:仅支持线下投放,库券需要局卷点; 248 | - **接口**:平台开通、接口创建、平台增加库存、接口生成二维码、接口核销; 249 | 250 | 251 | # 五、微信卡券第三方代制指引文档 252 | 253 | ## 1. 功能简介 254 | > 微信卡券第三方代制功能,让有运营能力或技术能力的第三方,为有卡券需求的合作商户(下文中简称“子商户”)提供卡券功能接入、使用及完整的营销闭环解决方案。 255 | 256 | - **资质报备**:需要合作商户授权并报备资质审核; 257 | - **创建卡券**:优惠券支持平台或接口代制,会员卡支持API代制; 258 | - **卡券服务**:卡券商品和服务由商户提供,全面显示为商户的LOGO,只能通过第三方公众号完成; 259 | - **主要优势** 260 | - 简化申请环节:第三方帮忙快速申请; 261 | - 降低账号要求:没有公众号的子商户也可以由第三方代为接入; 262 | - 降低资质门槛:不要求特殊资质,各行各业均可以接入; 263 | 264 | ## 2. 开放范围 265 | - **第三方代制功能**:面向微信公众平台所有已具备卡券功能能,且有代制需求的公众号; 266 | - **子商户功能**:面向所有卡券类目范围内的散户开放; 267 | - 资质证明:第三方公众号代为提交; 268 | - 卡券功能:第三方公众号代为使用卡券; 269 | - 子商户公众号:若有配置了子商户认证公众号,则卡券页面展现子商户公众号、无配额限制; 270 | - 数据存储:数据均存放在第三方公众号内; 271 | - **类目限制**:根据第三方配置的子商户的类目进行判断是否能够代制; 272 | - **制卷限制**:每月可为子商户代制10个`cardid`,每个库存不超过10000份;若子商户配置了认证公众号,则无制卷数量限制; 273 | 274 | 275 | ## 3. 申请指引 276 | ###3.1 申请要求 277 | - **第三方**:无需额外资质,已具备卡券功能的普通公众号,可自动升级; 278 | - **子商户**:有无公众号均可以接入; 279 | - 商户名称、LOGO:需要与授权函一致; 280 | - 接入类目:需要满足要求; 281 | - 授权函:手写加盖公章或签字、营业执照、经营者身份证; 282 | - 截止日期:需与授权协议中一致; 283 | - 公众号:若配置了认证公众号,将展现子商户的公众号; 284 | 285 | ### 3.2 接入流程 286 | - **第一步**:申请第三方代制能力 287 | - 认证的公众号; 288 | - 开通卡券功能; 289 | - **第二步**:接入并管理子商户 290 | - 提交子商户资料、协议; 291 | - 通过公众平台或API接口提交; 292 | - **第三步**:使用卷卡功能; 293 | - API接口创建卡券需要传入特有字段`子商户ID`; 294 | - 可以通过公众平台、接口返回值、子商户信息接口获取`子商户ID`; 295 | #### 3.2.1 申请第三方代制能力 296 | - **申请卡券功能**:申请卡券功能时,直接选择第三方角色,即可获得第三方代制能力; 297 | - **普通卡券商户**:可以通过商户信息中的,切换到第三方代制模式获得能力; 298 | 299 | #### 3.2.2 接入并管理子商户 300 | - **子商户接入** 301 | - 公众平台:通过卡券功能0卡券概况页面,提交子商户资质; 302 | - API接口:能够通过API接口提交审核; 303 | - **子商户管理** 304 | - 审核中的子商户不能删除; 305 | - 审核通过才能创建卡券; 306 | - 审核驳回和过期的散户可以修改重提; 307 | 308 | #### 3.2.3 第三方代子商户制卷 309 | - **导入门店** 310 | - 线下卡券:需要在公众平台导入门店; 311 | - 门店提交:第三方公众号在门店管理处,提交子商户门店,进审核地址准确性; 312 | **创建卡券** 313 | - 平台制卷:需要切换到代制模式,选择子商户,选择卷类型;会员卡需要接口开发; 314 | - API制券:需要计入特有字段子商户ID; 315 | - **创建会员卡**:仅支持*API接口*制卷; 316 | - **创建普通券**:支持公众平台或API接口代制,*任何类目*均可操作; 317 | - **创建朋友的卷**:支持公众平台或API接口代制,类目有限制; 318 | - 类目范围:有一定限制; 319 | - 收费标准:第三方代子商户制券时,微信向第三方收费;第三方如何向子商户收费可以具体情况而定,可以从中赚取利润(领取/核销/单次/包年/包月); 320 | - 点券奖励:开通奖励100点;门店一致奖励100点;子商户接入奖励200点;核销奖励2倍; 321 | 322 | #### 3.2.4 第三方代子商户发卷 323 | - **普通卷和会员卡**:二维码、公众号、H5页面,线上或线下领取;不支持跨公众号投放; 324 | - **朋友的卷**:线下方式投放,不支持公众号投放; 325 | 326 | #### 3.2.5 第三方代子商户销卷 327 | - **官方工具核销**:无需开发; 328 | - 卡券助手/微信公众平台:需要引导子商户电源关注卡券商户公众号,并绑定核销权限; 329 | - 自助核销: 由用户发现,全程由用户操作,实现快速核销;必须设置门店且绑定核销员; 330 | - **接口核销**:需要第三方自行开发,可以打通收银系统,进行更完整的记账; 331 | 332 | #### 3.2.5 第三方代子商户管理数据 333 | - **数据承载**:数据均承载在第三方公众号内,第三方可以通过下载数据或接口拉取数据; 334 | - **朋友的卷**:卷点都在第三方公众号内,下载流水详情后,可以分析商户交易记录; 335 | 336 | ## 5. 审核标准/违规处理 337 | 详见文档 -------------------------------------------------------------------------------- /doc/django/README.md: -------------------------------------------------------------------------------- 1 | # Django 入门 - 学习笔记 2 | ## 1. 简介 3 | > Django框架负责处理大部分Web开发的底层细节,我们可以专注开发web应用; 4 | 5 | - 快速开发:Python语言、数据库ORM系统; 6 | - 大量内置应用:后台管理 admin、用户认证 auth、会话系统sessions; 7 | - 安全性高:表单验证、SQL注入、跨站攻击; 8 | - 易于扩展; 9 | 10 | ## 2. 开发环境 11 | 12 | 安装开发环境: 13 | - `python` 14 | - `ipython` 15 | - `djanjo` 16 | 17 | 环境变量配置: 18 | - 将`PYTHON_HOME\Scripts`目录加入`PATH`环境变量; 19 | 20 | ## 3. 创建工程 21 | ### 3.1 工程基本结构 22 | 通过命令创建工程: 23 | 24 | ``` python 25 | django-admin startproject mysite 26 | ``` 27 | 28 | 工程结构: 29 | - `manage.py` 30 | - `mysite` 31 | - `__init__.py` 32 | - `settings.py` 33 | - `urls.py` 34 | - `wsgi.py` 35 | - `db.sqllite3` 36 | 37 | ### 3.2 manage.py 38 | `manage.py`是Django的一个用于管理任务的命令行工具。 39 | ``` 40 | # 启动服务 41 | python manage.py runserver 0.0.0.0:8080 42 | ``` 43 | - 使用该命令会启动的一个开发服务器,它使用纯`python`进行编写,可以快速进行开发。不要在开发环境使用该服务。 44 | - `runserver`服务器具备热部署的功能,但是如新增字段等某些操作还是需要重启服务器; 45 | 46 | ### 3.3 settings.py 47 | Django 的设置,配置文件,比如 DEBUG 的开关,静态文件的位置等。 48 | - `ALLOWED_HOSTS` :允许访问的IP域; 49 | - `INSTALLED_APPS`:已经安装的应用; 50 | - `MIDDLEWARE`: django的中间件; 51 | - `ROOT_URLCONF`:根目录; 52 | - `TEMPLATES`:模板引擎; 53 | - `DATABASES`:数据库; 54 | 55 | ### 3.4 urls.py 56 | 网址入口,关联到对应的views.py中的一个函数(或者generic类),访问网址就对应一个函数。 57 | ``` python 58 | urlpatterns = [ 59 | url(r'^admin/', admin.site.urls), 60 | ] 61 | ``` 62 | ### 3.5 wsgi.py 63 | `wsgi(Python Web Server Gateway Interface)`服务器网关接口,是Python语言定义的web服务器和web服务程序或者框架之间的一种简单而通用的接口。 64 | 65 | ### 3.6 \__init__.py 66 | 标识这是一个`python`的包; 67 | 68 | ## 4. 构建应用 69 | 70 | ### 4.1 创建应用 71 | 调用`manage.py`创建应用,会自动创建app目录: 72 | ``` python 73 | python manage.py startapp blog # blog 是一个app的名称 74 | ``` 75 | - 在`django`中,`project`是用多个`app`组成的; 76 | - 可以使用`manage.py`的自动化构建工具自动生成`app`的结构; 77 | 78 | 应用目录: 79 | - `views.py` - 定义视图访问函数; 80 | - `models.py` - 定义数据表; 81 | - `migrations` - 和数据库相关; 82 | - `test.py` - 测试; 83 | - `admin.py` - 给django自带的admin应用使用,管理数据库后台; 84 | 85 | 86 | ### 4.2 添加应用 87 | #### 4.2.1 添加自定义应用 88 | 在`settings.py`中的`INSTALLED_APPS`配置项中加入新增的应用; 89 | ``` python 90 | INSTALLED_APPS = [ 91 | 'django.contrib.admin', 92 | 'django.contrib.auth', 93 | 'django.contrib.contenttypes', 94 | 'django.contrib.sessions', 95 | 'django.contrib.messages', 96 | 'django.contrib.staticfiles', 97 | 'blog' # 自定义的应用 98 | ] 99 | ``` 100 | 也可以使用`apps.py`引入: 101 | ``` python 102 | INSTALLED_APPS = [ 103 | # ..... 104 | 'polls.apps.PollsConfig', 105 | ] 106 | ``` 107 | 108 | #### 4.2.2 默认应用 109 | 默认引入一些便利、通过的app,这些应用有可能对数据库有所依赖,如果不需要这些模块,可以将其删除: 110 | - `django.contrib.admin` – 后台管理模块; 111 | - `django.contrib.auth` – 权限控制模块; 112 | - `django.contrib.contenttypes` – 一个用于引入文档类型的框架; 113 | - `django.contrib.sessions` – 会话框架; 114 | - `django.contrib.messages` –消息框架; 115 | - `django.contrib.staticfiles` – 静态文件管理框架; 116 | 117 | 使用`migrate`指令可以创建app依赖的数据库表; 118 | ``` 119 | python manage.py migrate 120 | ``` 121 | 122 | ### 4.4 定义视图访问函数 123 | 124 | #### 4.4.1 访问函数 125 | `views.py`文件定义了视图,需要在其中定义视图访函数,并在`urls.py`文件中定义其对用的映射URL。 126 | - 视图访问函数需要返回一个`HttpResponse`对象或引发抛出异常,例如`Http404`; 127 | - `HttpResponse`可以使用已渲染的视图及`request`进行构造; 128 | - 使用`loader.get_template('blog_list.html')`可以获取视图模板; 129 | - 使用`template.render(context)`可以对模板进行渲染; 130 | - 可以使用`request.POST`和`request.GET`获取表单提交的参数; 131 | 132 | ``` python 133 | def vote(request, question_id): 134 | question = get_object_or_404(Question, pk=question_id) 135 | try: 136 | selected_choice = question.choice_set.get(pk=request.POST['choice']) 137 | except(KeyError, Choice.DoesNotExist): 138 | return render(request, 'polls/detail.html', { 139 | 'question': question, 140 | 'error_message': 'You did not select a choice' 141 | }) 142 | else: 143 | selected_choice.votes += 1 144 | selected_choice.save() 145 | return HttpResponseRedirect(reverse('polls:results', args=question_id)) 146 | ``` 147 | 148 | #### 4.4.2 快捷定义 149 | - 可以使用`render(request, template_name, context)`可以快捷构造一个`HttpResponse`; 150 | 151 | ```python 152 | from django.shortcuts import render 153 | 154 | def index(request): 155 | latest_question_list = Question.objects.order_by('-pub_date')[:5] 156 | context = {'latest_question_list': latest_question_list} 157 | return render(request, 'polls/index.html', context) 158 | ``` 159 | 160 | #### 4.4.3 抛出异常 161 | 当对象找不到时可以使用`try except`捕获异常,并使用`raise Http404`抛出404错误: 162 | ```python 163 | def detail(request, question_id): 164 | try: 165 | question = Question.objects.get(pk=question_id) 166 | except Question.DoesNotExist: 167 | raise Http404("Question does not exists") 168 | return render(request, 'polls/detail.html', {'question': question}) 169 | ``` 170 | 可以使用`get_object_or_404()`简化这个过程; 171 | 172 | 173 | #### 4.4.4 重定向 174 | 可以使用`HttpResponseRedirect`进行重定向,重定向需要传入一个`URL`,需要使用`reverse`函数将模板名称和参数转换成URL进行访问: 175 | ``` python 176 | def vote(request, question_id): 177 | # ...... 178 | return HttpResponseRedirect(reverse('polls:results', args=question_id)) 179 | ``` 180 | 181 | #### 4.4.5 抽象视图 182 | 利用抽象视图,可以专注于特殊数据提取的逻辑与返回模板的名称,而不关心结果怎么放到视图中、视图渲染的过程、通用的数据提取逻辑,可以进一步简化视图访问函数的代码。 183 | ``` python 184 | # 列表抽象视图 185 | class IndexView(generic.ListView): 186 | # 视图模板 187 | template_name = 'polls/index.html' 188 | # 结果保存在context里的名称 189 | context_object_name = 'latest_question_list' 190 | 191 | # 获取数据集合的方法 192 | def get_queryset(self): 193 | return Question.objects.order_by('-pub_date')[:5] 194 | 195 | #详情抽象视图 196 | class DetailView(generic.DetailView): 197 | # 模型类 198 | model = Question 199 | # 视图模板 200 | template_name = 'polls/detail.html' 201 | 202 | ``` 203 | 抽象视图对URL的配置也有一定的要求: 204 | - 视图使用`views.类名.as_view()`; 205 | - 参数名称有约定,如主键使用`pk`; 206 | 207 | ``` 208 | urlpatterns = [ 209 | url(r'^$', views.IndexView.as_view(), name='index'), 210 | url(r'^(?P[0-9]+)$', views.DetailView.as_view(), name="detail"), 211 | url(r'^(?P[0-9]+)/results/$', views.ResultView.as_view() , name="results"), 212 | url(r'^(?P[0-9]+)/vote/$', views.vote, name="vote"), 213 | ] 214 | ``` 215 | 216 | ### 4.5 定义视图函数URL 217 | #### 4.5.1 直接定义 218 | 先使用`form...import`语句导入函数,再使用`url()`定义访问的URL,第一个参数为匹配URL的正则表达式,第二个参数为对应的访问函数。 219 | ``` python 220 | from django.conf.urls import include, url 221 | from django.contrib import admin 222 | from blog.views import hello 223 | urlpatterns = [ 224 | url(r'^admin/', include(admin.site.urls)), 225 | url(r'^$', show_list), 226 | url(r'^blog/(\d+)$', show_blog), 227 | ] 228 | ``` 229 | 230 | #### 4.5.2 配置模块的urls.py 231 | 也可以在`app/urls.py`目录下定义局部的`urls.py`: 232 | ``` python 233 | from django.conf.urls import url 234 | from . import views 235 | urlpatterns = [ 236 | url(r'^$', views.index, name='index'), 237 | ] 238 | ``` 239 | 在全局的`urls.py`中进行引用,并为模块设定统一的前缀: 240 | - 当遇到`include`函数时,`django`总是会截断已匹配的部分,然后将剩余部分传递到下一个`URLconf`中; 241 | - 当引用另外一个`URL patterns`时,总是需要使用`include()`函数; 242 | 243 | ``` python 244 | from django.conf.urls import include, url 245 | from django.contrib import admin 246 | 247 | urlpatterns = [ 248 | url(r'^polls/', include('polls.urls')), 249 | url(r'^admin/', admin.site.urls), 250 | ] 251 | ``` 252 | 253 | #### 4.5.3 url()函数 254 | 函数参数: 255 | - `regex` - 匹配URL的正则表达式 256 | - 不限定根域名及`GET`/`POST`请求的参数; 257 | - 具备较强的匹配性能; 258 | - 被正则表达式捕获的分组,会按照顺序依次作为参数传入; 259 | - 如果使用命名分组`(?P)`,那么将会作为关键词参数传入; 260 | - `view` - 视图处理函数 261 | - 传入视图处理函数的第一个参数固定为`HttpRequest`; 262 | - `kwargs` - 关键词参数 263 | - 可以传递任意的关键词参数到视图中; 264 | - `name` - 命名URL 265 | - 可以避免混淆发生,可以使用`url`命令访问指定的url‘; 266 | 267 | ``` python 268 | urlpatterns = [ 269 | # ex: /polls/ 270 | url(r'^$', views.index, name='index'), 271 | # ex: /polls/5/ 272 | url(r'^(?P[0-9]+)$', views.detail, name="detail"), 273 | # ex: /polls/5/results/ 274 | url(r'^(?P[0-9]+)/results/$', views.results, name="results"), 275 | # ex: /polls/5/vote/ 276 | url(r'^(?P[0-9]+)/vote/$', views.vote, name="vote"), 277 | ] 278 | ``` 279 | 280 | #### 4.5.4 URL的命名空间 281 | 可以在`urlpattern`前定义`app_name`变量,指定其命名空间: 282 | ``` python 283 | app_name = "polls" 284 | 285 | urlpatterns = [ 286 | ] 287 | ``` 288 | 289 | #### 4.5.5 访问命名URL 290 | 可以在模板中使用`url`命令访问命名的URL,而不是依赖于特定的URL字符串: 291 | ``` html 292 | {{ question.question_text }} 293 | ``` 294 | 或使用命名空间前缀进行访问: 295 | ``` 296 | {{ question.question_text }} 297 | ``` 298 | 299 | 300 | ### 4.6 数据模型 301 | #### 4.6.1 基本概念 302 | - `Django`的模型基于DRY原则,即仅在一个地方定义数据模型,并自动生成数据库结构; 303 | - 使用`migrations`可以自动维护数据库结构,使其满足当前的模型; 304 | 305 | #### 4.6.2 构建模型 306 | - 每个`Django`的模型都是`django.db.models.Model`的子类; 307 | - 每个模型都会定义一些类变量,代表其映射的数据库字段; 308 | - 字段名称即为`python`的字段名、也是数据的列名; 309 | - 常用字段类型: 310 | - `DateTimeField` 311 | - `CharField` 312 | - `IntegerField` 313 | 314 | 315 | Django 模型是与数据库相关的,与数据库相关的代码一般写在 `models.py` 中: 316 | ``` python 317 | class Blog(models.Model): 318 | title = models.CharField(max_length=50) 319 | content = models.TextField() 320 | counter = models.IntegerField() 321 | pubDate = models.DateField(auto_now_add=True) 322 | author = models.ForeignKey(Author) 323 | 324 | def __unicode__(self): 325 | return self.title 326 | ``` 327 | #### 4.6.3 生成数据库表 328 | 需要使用命令同步数据库,生成数据库表: 329 | ``` python 330 | python manage.py makemigrations 331 | python manage.py migrate 332 | ``` 333 | - `makemigrations`命令告诉`Django`模型发生改变; 334 | - `migrate`命令应用变更,执行数据库变更的脚本; 335 | - 生成库表的名称为`模块名_小写类名`; 336 | - 主键会自动生成,命名为`id`,在`MySql`会配置为自增字段; 337 | - 外键的命名为`对端对象名_id`; 338 | - `Django`通过特殊的库表`django_migrations`判断哪些变更已经执行过了、哪些没执行过; 339 | 340 | #### 4.6.4 数据访问API 341 | - `get()` 342 | - `filter()` 343 | - `exclude()` 344 | 345 | 字段查询使用双下划线作为条件限定和对象导航:`field__lookuptype=value`; 346 | - `lte`,`gte`,`gt`,`lt`:比较符; 347 | - `iexact`,`exact`:严格匹配,如大小写; 348 | - `contains`:包含; 349 | - `startswith`,`endswith`:开头、结尾匹配; 350 | 351 | ``` python 352 | # 获取全部对象 353 | from polls.models import Question, Choice 354 | # 根据字段获取对象 355 | Question.objects.filter(id=1) 356 | # 模糊查询 357 | Question.objects.filter(question_text__contains='up') 358 | # 创建关联对象 359 | q.choice_set.create(choice_text='The sky', votes=0) 360 | # 获取关联对象 361 | q.choice_set.all() 362 | ``` 363 | 364 | 365 | ### 4.7 视图模板 366 | #### 4.7.1 视图模板配置 367 | - `TEMPLATES`:配置节点描述了Django的模板配置信息; 368 | - `APP_DIRS`:为`Ture`是会查找每个安装应用`INSTALLED_APP`子文件夹内部的`templates`文件夹; 369 | - 需要在`APP`的子目录下简历`templates`文件夹,并再建立子文件夹作为模板的命名空间,避免重复; 370 | - 模板通常的路径格式:`polls/templates/polls/index.html`; 371 | 372 | Django 的模板系统会自动找到app下面的templates文件夹中的模板文件: 373 | ``` 374 | 375 | 376 | 377 | 378 | 博客列表 379 | 380 | 381 | {% for blog in blogs %} 382 |

{{ blog.title }}

383 | {% endfor %} 384 | 385 | 386 | ``` 387 | 模板支持一些基本表达式语法: 388 | ``` 389 | 390 | {{ string }} 391 | {{ info_dict.content }} 392 | 393 | 394 | {% for i in TutorialList %} 395 | {{ i }} 396 | {% endfor %} 397 | 398 | 399 | {% if var >= 90 %} 400 | 成绩优秀,自强学堂你没少去吧!学得不错 401 | {% elif var >= 60 %} 402 | 需要努力 403 | {% else %} 404 | 不及格啊,大哥!多去自强学堂学习啊! 405 | {% endif %} 406 | ``` 407 | 408 | ### 4.8 后台管理 409 | 需要先为管理后台创建一个用户: 410 | ``` python 411 | python manage.py createsuperuser 412 | ``` 413 | 414 | 修改模块的`admin.py`文件,注册模型,登录`http://localhost:8000/admin/ `即可进入管理页面: 415 | ``` python 416 | from django.contrib import admin 417 | from .models import Blog, Author 418 | 419 | # Register your models here. 420 | admin.site.register(Blog) 421 | admin.site.register(Author) 422 | ``` 423 | 推荐定义 Model 的时候 写一个 `__unicode__` 函数(或 `__str__`函数),以便支持更友好的展示效果 424 | ``` python 425 | def __unicode__(self): 426 | return self.title 427 | ``` 428 | 429 | 430 | 431 | ## 5. 连接MySQL数据库 432 | ### 5.1 配置DATABASE 433 | ``` python 434 | DATABASES = { 435 | 'default': { 436 | 'ENGINE': 'django.db.backends.mysql', 437 | 'NAME': 'blog_system', 438 | 'USER': 'root', 439 | 'PASSWORD': 'root', 440 | 'HOST': '192.168.125.134', 441 | 'PORT': '3306', 442 | } 443 | } 444 | ``` 445 | 446 | ### 5.2 安装MySQL驱动 447 | - 下载并安装:[Microsoft Visual C++ 9.0 is required](http://www.microsoft.com/en-us/download/confirmation.aspx?id=44266) 448 | - 下载并安装:[mysql-connector-python](https://dev.mysql.com/downloads/connector/python/) 449 | - 检查安装: 450 | ``` python 451 | pip install MySQL-python 452 | # Requirement already satisfied (use --upgrade to upgrade): MySQL-python in d:\python27\lib\site-packages 453 | ``` 454 | - 运行迁移命令,创建数据库表: 455 | ``` 456 | python manage.py migrate 457 | ``` 458 | ## 6. 测试 459 | ### 6.1 创建测试 460 | - 根据约定,应用的测试一般放在`test.py`文件中; 461 | - 测试系统会自动加载文件名为`test`开头的文件作为测试; 462 | 463 | ``` python 464 | class QuestionMethodTests(TestCase): 465 | def test_was_published_recently_with_future_question(self): 466 | time = timezone.now() + datetime.timedelta(days=30) 467 | future_question = Question(pub_date=time) 468 | self.assertIs(future_question.was_published_recently(), False) 469 | 470 | ``` 471 | 472 | 在校验预期结果时,可以使用断言: 473 | - `assertQuerysetEqual` 474 | - `assertContains` 475 | - `assertIs` 476 | 477 | 创建测试需要遵守一些约定: 478 | - 测试不同改的`model`或者`view`需要创建不同的类; 479 | - 不同的方法测试不同的条件; 480 | - 测试方法的命名需要描述准确; 481 | 482 | ### 6.2 执行测试 483 | 可以命令执行测试用例: 484 | ``` 485 | python manage.py test polls 486 | ``` 487 | 488 | 测试执行的过程: 489 | - 在`polls`程序中寻找测试用例文件; 490 | - 找到继承自`django.test.TestCase`的子类; 491 | - 创建测试数据库; 492 | - 找到以`test`作为开头的测试方法; 493 | - 执行测试用例; 494 | 495 | ## 7. 静态文件 496 | `django.contrib.staticfiles`会收集各个应用的静态文件,并放置到一个统一的位置,便于访问。 497 | 498 | ### 7.1 配置目录 499 | `STATICFILES_FINDERS`配置了静态文件的查找器,`STATICFILES_DIRS`配置了静态文件的路径。 500 | ``` python 501 | [ 502 | # 找到STATICFILES_DIRS配置中的目录 503 | 'django.contrib.staticfiles.finders.FileSystemFinder', 504 | # 每个应用下的static子目录中的文件 505 | 'django.contrib.staticfiles.finders.AppDirectoriesFinder', 506 | ] 507 | ``` 508 | 509 | -------------------------------------------------------------------------------- /doc/hadoop/README.md: -------------------------------------------------------------------------------- 1 | 2 | # Hadoop 大数据平台 - 学习笔记 3 | 4 | ## 1. 简介 5 | > Apache Hadoop软件库是一个框架,允许在集群服务器上使用简单的编程模型对大数据集进行分布式处理。Hadoop被设计成能够从单台服务器扩展到数以千计的服务器,每台服务器都有本地的计算和存储资源。Hadoop的高可用性并不依赖硬件,其代码库自身就能在应用层侦测并处理硬件故障,因此能基于服务器集群提供高可用性的服务。 6 | ![生态系统](./1478283337935.png) 7 | - `HDFS`:分布式文件系统,数据保存在计算机集群上,为HBase等工具提供了基础; 8 | - `MapReduce`:分布式、并行处理编程模型,将任务分成map和reduce,能够实现快速访问数据; 9 | - `HBase`:建立在HDFS上,面向列的NoSQL数据库,用于读/写大量数据。 10 | - `Zookeeper`:分布式协调服务,运行在计算机集群上面,用于管理Hadoop操作; 11 | - `Pig`:MapReduce编程的复杂性抽象,其编译期将`Pig Latin`脚本语言翻译成MR程序序列; 12 | - `Hive`:类似SQL的高级语言,在Hadoop上查询语句; 13 | - `Sqoop`:一种用于在关系数据库、数据仓库和Hadoop之间转移数据的连接工具; 14 | - `Flume`:用于收集、汇总大数据、将大量数据转移到HDFS的服务; 15 | 16 | ### 1.1 时代背景 17 | - 数据量、数据增长数据越来越快; 18 | - 通过挖掘数据获得价值; 19 | - 随着数据量越来越大,数据分析可能遇到各种瓶颈; 20 | 21 | ### 1.2 大数据关键技术 22 | - MapReduce 23 | - BigTable 24 | - GFS 25 | 26 | ### 1.3 革命性变化 27 | - 降低成本、使用PC及代替大型机、高端存储; 28 | - 软件容错硬件故障视为常态,通过软件保证可靠性; 29 | - 简化并行分布式计算,无需控制节点同步; 30 | 31 | ### 1.4 Hadoop 32 | - 属于Apache旗下的开源软件; 33 | - 是一个分部署存储及分布式计算平台; 34 | 35 | #### 1.4.1 核心组成 36 | - HDFS :分布式文件系统,存储海量的数据; 37 | - MapReduce:并行处理框架,实现任务分解和调度; 38 | 39 | #### 1.4.2 作用 40 | - 搭建大型数据仓库、PB级数据存储、分析、处理、统计; 41 | - 搜索引擎、商业智能、日志分析、数据挖掘; 42 | 43 | #### 1.4.3 优势 44 | - 高扩展:可以方便的扩展硬件增加处理能力; 45 | - 低成本:基于廉价硬件堆叠系统、通过软件容错实现系统可靠性; 46 | - 成熟的生态圈:有很多周边工具、技术栈完整; 47 | 48 | #### 1.4.4 应用情况 49 | - 国内外IT公司均利用官方; 50 | - 业界大数据平台的首选方案; 51 | - 人才需求广泛(开发/运维); 52 | 53 | #### 1.4.5 生态系统 54 | - MapReduce/HDFS 55 | - HIVE : 不用编写任务,直接编写SQL语句、降低Hadoop的门槛; 56 | - HBASE:存储结构化数据的分布式数据库,放弃了事务特性、追求更高的扩展; 57 | - Zookeeper:监控Hadoop集群状态、维护节点之间的数据一致性; 58 | 59 | #### 1.4.6 版本 60 | - 1.X 61 | - 2.X 62 | 63 | ## 2. 安装Hadoop 64 | 65 | ### 2.1 安装JDK 66 | 在Ubuntu环境下安装JDK 1.7: 67 | ``` bash 68 | # apt-get install openjdk-7-jdk 69 | ``` 70 | 71 | 配置环境变量: 72 | 73 | 74 | ### 2.2 安装Hadoop 75 | #### 2.2.1 下载 76 | 下载1.2.1版本的Hadoop: 77 | ``` 78 | wget https://archive.apache.org/dist/hadoop/common/hadoop-1.2.1/hadoop-1.2.1.tar.gz 79 | ``` 80 | 各种版本可以在下载:[Hadoop发布版本下载地址](https://archive.apache.org/dist/hadoop/common/) 81 | 82 | 解压缩安装包: 83 | ``` 84 | tar -zxvf hadoop-1.2.1.tar.gz 85 | ``` 86 | 87 | #### 2.2.2 修改配置文件 88 | 配置`/conf/hadoop-evn.sh`: 89 | ``` bash 90 | export JAVA_HOME=/root/data/jdk/jdk1.8.0_92 91 | ``` 92 | 93 | 配置`/conf/core-site.xml`(Haddop核心配置): 94 | ``` xml 95 | 96 | 97 | 98 | hadoop.tmp.dir 99 | /hadoop 100 | 101 | 102 | 103 | 104 | dfs.name.dir 105 | /hadoop/name 106 | 107 | 108 | 109 | 110 | fs.default.name 111 | hdfs://127.0.0.1:9000 112 | 113 | 114 | 115 | ``` 116 | 117 | 配置`/conf/hdfs-site.xml`(HDFS存储配置): 118 | ``` xml 119 | 120 | 121 | 122 | dfs.data.dir 123 | /hadoop/data 124 | 125 | 126 | ``` 127 | 128 | 配置`/conf/mapred-site.xml`(Map/Reduce配置): 129 | ``` xml 130 | 131 | 132 | 133 | mapred.job.tracker 134 | http://127.0.0.1:9001 135 | 136 | 137 | ``` 138 | 139 | #### 2.2.3 修改环境变量 140 | 配置`/etc/profile`(环境变量): 141 | ``` bash 142 | #hadoop 143 | HADOOP_HOME=/root/data/hadoop-1.2.1 144 | PATH=$HADOOP_HOME/bin:$PATH 145 | export HADOOP_HOME_WARN_SUPPRESS=1 # 防止出现警告 146 | ``` 147 | 148 | #### 2.2.4 初始化工作 149 | 格式化`namenode`: 150 | ``` bash 151 | hadoop namenode -format 152 | ``` 153 | 启动服务: 154 | ``` bash 155 | sh start-all.sh 156 | ``` 157 | 158 | 检查服务: 159 | ``` bash 160 | jps 161 | # 6496 Jps 162 | # 6260 JobTracker 163 | # 6421 TaskTracker 164 | # 6181 SecondaryNameNode 165 | # 5896 NameNode 166 | # 6042 DataNode 167 | ``` 168 | 169 | 检查存储: 170 | ``` bash 171 | hadoop fs -ls / 172 | # drwxr-xr-x - root supergroup 0 2016-10-29 00:08 /hadoop 173 | ``` 174 | 175 | ## 3. HDFS 文件系统 176 | > Hadoop分布式文件系统(`HDFS`,`Hadoop Distributed File System` )被设计成适合运行在通用硬件(commodity hardware)上的分布式文件系统。HDFS有着高容错性(fault-tolerant)的特点,并且设计用来部署在低廉的(low-cost)硬件上。 177 | > 而且它提供高吞吐量(high throughput)来访问应用程序的数据,适合那些有着超大数据集(large data set)的应用程序。HDFS放宽了(relax)POSIX的要求(requirements)这样可以实现流的形式访问(streaming access)文件系统中的数据。 178 | 179 | ### 3.1 基本概念 180 | - `Block` - HDFS的文件被分成块进行存储,每个块的大小默认为`64MB`,块是文件存储处理的逻辑单元; 181 | - `NameNode` - 管理节点,存放文件元数据;包括文件和数据块的映射表、数据块和数据节点的映射表; 182 | - `DataNode`- 工作节点,存放真正的数据块; 183 | 184 | **HDFS体系结构图:** 185 | ![HDFS](./1477760831760.png) 186 | 187 | **HDFS的特点:** 188 | - 数据冗余、硬件容错; 189 | - 流式数据访问(一次存储、多次读取); 190 | - 存储大文件; 191 | - 适合批量读写、吞吐量高、一次接卸多次读取; 192 | - 不适合交互式应用,低延迟很难满足; 193 | 194 | ### 3.2 数据管理与容错 195 | - **数据块副本:**每个数据块3个副本,分布在两个机架内的三个节点;防止单节点故障和机架故障; 196 | - **心跳检测:**`DataNode`定期向`NameNode`发送心跳消息,发送节点状态; 197 | - **SecondaryNameNode:**二级NameNode定期同步元数据镜像文件和修改日志,NameNode故障时二级NameNode工作,保证高可用性; 198 | 199 | ### 3.3 文件读写 200 | **文件读取流程:** 201 | - 客户端先向`NameNode`发起文件读取请求(文件名/路径),`NameNode`查询元数据返回客户端(包含块及其DataNode位置); 202 | - 客户端找到`DataNode`,读取`Block`并组装成文件; 203 | 204 | **文件写入流程:** 205 | - 文件拆分成`Block`; 206 | - 客户端通知`NameNode`,`NameNode`返回空闲的DataNods; 207 | - 客户端对`Blocks`进行写入操作; 208 | - 执行流水线复制更新`NameNode`的元数据; 209 | - 循环写入剩余的`Blocks`; 210 | 211 | ### 3.4 基础使用 212 | 格式化: 213 | ``` bash 214 | hadoop namenode -format 215 | ``` 216 | 217 | 基本命令: 218 | ``` bash 219 | # 打印文件 220 | hadoop fs -ls [path] 221 | 222 | # 建立目录 223 | hadoop fs -mkdir [dir_name] 224 | 225 | # 上传文件 226 | hadoop fs -pu [filename] 227 | 228 | # 查看文件 229 | hadoop fs -cat [filename] 230 | 231 | # 下载文件 232 | hadoop fs -get [src_name] [dis_name] 233 | 234 | # 文件系统使用报告 235 | hadoop dfsadmin -report 236 | ``` 237 | 238 | ## 4. MapReduce 并行计算框架 239 | 240 | ### 4.1 基本原理 241 | > 分而治之原理,将一个大任务分解成多个小任务(Map),并行执行后再合并结果(Reduce); 242 | 243 | ![MR举例](./1477845188688.png) 244 | - 切分任务; 245 | - 分别统计; 246 | - 组合规约; 247 | - 汇总统计; 248 | > 例如统计100G的日志文件中,出现次数最多的IP地址,可以分为以下步骤: 249 | > - 日志文件按照时间区段进行分解到不同的任务节点上(Map); 250 | > - 任务节点分别统计各个IP地址出现的次数; 251 | > - 任务节点将统计结果,根据一定规则汇总规约(Reduce); 252 | > - 最终产生排序结果; 253 | 254 | 255 | ### 4.2 运行流程 256 | 257 | #### 4.2.1 组成部分 258 | - `Job` - 整体的作业; 259 | - `Task` - 任务,一个`Job`由多个`Task`组成; 260 | - `MapTask` 261 | - `ReduceTask` 262 | - `JobTracker` - 管理节点,负责分解Map任务和Reduce任务; 263 | - `TaskTracker` - 任务处理节点,负责处理任务; 264 | - `MapTaskTracker` 265 | - `ReduceTaskTracker` 266 | 267 | ####4.2.2 JobTracker 268 | - 作业调度; 269 | - 任务分配、监控任务执行进度; 270 | - 监控TaskTracker的状态; 271 | 272 | #### 4.2.3 TaskTracker 273 | - 执行任务; 274 | - 汇报任务状态; 275 | 276 | #### 4.2.4 执行过程 277 | ![MR执行过程](./1477848141097.png) 278 | - 任务提交到`JboTracker`; 279 | - 数据分片; 280 | - Map端分配Map任务,由`MapTaskTracker`处理; 281 | - 产生中间结果KEY-VALUE对; 282 | - Reduce端分配Reudce任务,由`ReduceTaskTracker`处理; 283 | - 写回结果的HSFS; 284 | 285 | ### 4.3 容错机制 286 | - 重复执行:重复执行过任务4次后放弃; 287 | - 推测执行:某个节点计算速度异常时,另外找一个节点负责处理; 288 | 289 | Hadoop 大数据平台 - 学习笔记 290 | 291 | 01. 写字台 292 | 293 | 294 | Hadoop 大数据平台 - 学习笔记 295 | 1. 简介 296 | 1.1 时代背景 297 | 1.2 大数据关键技术 298 | 1.3 革命性变化 299 | 1.4 Hadoop 300 | 1.4.1 核心组成 301 | 1.4.2 作用 302 | 1.4.3 优势 303 | 1.4.4 应用情况 304 | 1.4.5 生态系统 305 | 1.4.6 版本 306 | 2. 安装Hadoop 307 | 2.1 安装JDK 308 | 2.2 安装Hadoop 309 | 2.2.1 下载 310 | 2.2.2 修改配置文件 311 | 2.2.3 修改环境变量 312 | 2.2.4 初始化工作 313 | 3. HDFS 文件系统 314 | 3.1 基本概念 315 | 3.2 数据管理与容错 316 | 3.3 文件读写 317 | 3.4 基础使用 318 | 4. MapReduce 并行计算框架 319 | 4.1 基本原理 320 | 4.2 运行流程 321 | 4.2.1 组成部分 322 | 4.2.2 JobTracker 323 | 4.2.3 TaskTracker 324 | 4.2.4 执行过程 325 | 4.3 容错机制 326 | 1. 简介 327 | 328 | Apache Hadoop软件库是一个框架,允许在集群服务器上使用简单的编程模型对大数据集进行分布式处理。Hadoop被设计成能够从单台服务器扩展到数以千计的服务器,每台服务器都有本地的计算和存储资源。Hadoop的高可用性并不依赖硬件,其代码库自身就能在应用层侦测并处理硬件故障,因此能基于服务器集群提供高可用性的服务。 329 | 生态系统 330 | 331 | HDFS:分布式文件系统,数据保存在计算机集群上,为HBase等工具提供了基础; 332 | MapReduce:分布式、并行处理编程模型,将任务分成map和reduce,能够实现快速访问数据; 333 | HBase:建立在HDFS上,面向列的NoSQL数据库,用于读/写大量数据。 334 | Zookeeper:分布式协调服务,运行在计算机集群上面,用于管理Hadoop操作; 335 | Pig:MapReduce编程的复杂性抽象,其编译期将Pig Latin脚本语言翻译成MR程序序列; 336 | Hive:类似SQL的高级语言,在Hadoop上查询语句; 337 | Sqoop:一种用于在关系数据库、数据仓库和Hadoop之间转移数据的连接工具; 338 | Flume:用于收集、汇总大数据、将大量数据转移到HDFS的服务; 339 | 1.1 时代背景 340 | 341 | 数据量、数据增长数据越来越快; 342 | 通过挖掘数据获得价值; 343 | 随着数据量越来越大,数据分析可能遇到各种瓶颈; 344 | 1.2 大数据关键技术 345 | 346 | MapReduce 347 | BigTable 348 | GFS 349 | 1.3 革命性变化 350 | 351 | 降低成本、使用PC及代替大型机、高端存储; 352 | 软件容错硬件故障视为常态,通过软件保证可靠性; 353 | 简化并行分布式计算,无需控制节点同步; 354 | 1.4 Hadoop 355 | 356 | 属于Apache旗下的开源软件; 357 | 是一个分部署存储及分布式计算平台; 358 | 1.4.1 核心组成 359 | 360 | HDFS :分布式文件系统,存储海量的数据; 361 | MapReduce:并行处理框架,实现任务分解和调度; 362 | 1.4.2 作用 363 | 364 | 搭建大型数据仓库、PB级数据存储、分析、处理、统计; 365 | 搜索引擎、商业智能、日志分析、数据挖掘; 366 | 1.4.3 优势 367 | 368 | 高扩展:可以方便的扩展硬件增加处理能力; 369 | 低成本:基于廉价硬件堆叠系统、通过软件容错实现系统可靠性; 370 | 成熟的生态圈:有很多周边工具、技术栈完整; 371 | 1.4.4 应用情况 372 | 373 | 国内外IT公司均利用官方; 374 | 业界大数据平台的首选方案; 375 | 人才需求广泛(开发/运维); 376 | 1.4.5 生态系统 377 | 378 | MapReduce/HDFS 379 | HIVE : 不用编写任务,直接编写SQL语句、降低Hadoop的门槛; 380 | HBASE:存储结构化数据的分布式数据库,放弃了事务特性、追求更高的扩展; 381 | Zookeeper:监控Hadoop集群状态、维护节点之间的数据一致性; 382 | 1.4.6 版本 383 | 384 | 1.X 385 | 2.X 386 | 2. 安装Hadoop 387 | 388 | 2.1 安装JDK 389 | 390 | 在Ubuntu环境下安装JDK 1.7: 391 | 392 | # apt-get install openjdk-7-jdk 393 | 配置环境变量: 394 | 395 | 2.2 安装Hadoop 396 | 397 | 2.2.1 下载 398 | 399 | 下载1.2.1版本的Hadoop: 400 | 401 | wget https://archive.apache.org/dist/hadoop/common/hadoop-1.2.1/hadoop-1.2.1.tar.gz 402 | 各种版本可以在下载:Hadoop发布版本下载地址 403 | 404 | 解压缩安装包: 405 | 406 | tar -zxvf hadoop-1.2.1.tar.gz 407 | 2.2.2 修改配置文件 408 | 409 | 配置/conf/hadoop-evn.sh: 410 | 411 | export JAVA_HOME=/root/data/jdk/jdk1.8.0_92 412 | 配置/conf/core-site.xml(Haddop核心配置): 413 | 414 | 415 | 416 | 417 | hadoop.tmp.dir 418 | /hadoop 419 | 420 | 421 | 422 | 423 | dfs.name.dir 424 | /hadoop/name 425 | 426 | 427 | 428 | 429 | fs.default.name 430 | hdfs://127.0.0.1:9000 431 | 432 | 433 | 434 | 配置/conf/hdfs-site.xml(HDFS存储配置): 435 | 436 | 437 | 438 | 439 | dfs.data.dir 440 | /hadoop/data 441 | 442 | 443 | 配置/conf/mapred-site.xml(Map/Reduce配置): 444 | 445 | 446 | 447 | 448 | mapred.job.tracker 449 | http://127.0.0.1:9001 450 | 451 | 452 | 2.2.3 修改环境变量 453 | 454 | 配置/etc/profile(环境变量): 455 | 456 | #hadoop 457 | HADOOP_HOME=/root/data/hadoop-1.2.1 458 | PATH=$HADOOP_HOME/bin:$PATH 459 | export HADOOP_HOME_WARN_SUPPRESS=1 # 防止出现警告 460 | 2.2.4 初始化工作 461 | 462 | 格式化namenode: 463 | 464 | hadoop namenode -format 465 | 启动服务: 466 | 467 | sh start-all.sh 468 | 检查服务: 469 | 470 | jps 471 | # 6496 Jps 472 | # 6260 JobTracker 473 | # 6421 TaskTracker 474 | # 6181 SecondaryNameNode 475 | # 5896 NameNode 476 | # 6042 DataNode 477 | 检查存储: 478 | 479 | hadoop fs -ls / 480 | # drwxr-xr-x - root supergroup 0 2016-10-29 00:08 /hadoop 481 | 3. HDFS 文件系统 482 | 483 | Hadoop分布式文件系统(HDFS,Hadoop Distributed File System )被设计成适合运行在通用硬件(commodity hardware)上的分布式文件系统。HDFS有着高容错性(fault-tolerant)的特点,并且设计用来部署在低廉的(low-cost)硬件上。 484 | 而且它提供高吞吐量(high throughput)来访问应用程序的数据,适合那些有着超大数据集(large data set)的应用程序。HDFS放宽了(relax)POSIX的要求(requirements)这样可以实现流的形式访问(streaming access)文件系统中的数据。 485 | 3.1 基本概念 486 | 487 | Block - HDFS的文件被分成块进行存储,每个块的大小默认为64MB,块是文件存储处理的逻辑单元; 488 | NameNode - 管理节点,存放文件元数据;包括文件和数据块的映射表、数据块和数据节点的映射表; 489 | DataNode- 工作节点,存放真正的数据块; 490 | HDFS体系结构图: 491 | 492 | HDFS 493 | 494 | HDFS的特点: 495 | 496 | 数据冗余、硬件容错; 497 | 流式数据访问(一次存储、多次读取); 498 | 存储大文件; 499 | 适合批量读写、吞吐量高、一次接卸多次读取; 500 | 不适合交互式应用,低延迟很难满足; 501 | 3.2 数据管理与容错 502 | 503 | 数据块副本:每个数据块3个副本,分布在两个机架内的三个节点;防止单节点故障和机架故障; 504 | 心跳检测:DataNode定期向NameNode发送心跳消息,发送节点状态; 505 | SecondaryNameNode:二级NameNode定期同步元数据镜像文件和修改日志,NameNode故障时二级NameNode工作,保证高可用性; 506 | 3.3 文件读写 507 | 508 | 文件读取流程: 509 | 510 | 客户端先向NameNode发起文件读取请求(文件名/路径),NameNode查询元数据返回客户端(包含块及其DataNode位置); 511 | 客户端找到DataNode,读取Block并组装成文件; 512 | 文件写入流程: 513 | 514 | 文件拆分成Block; 515 | 客户端通知NameNode,NameNode返回空闲的DataNods; 516 | 客户端对Blocks进行写入操作; 517 | 执行流水线复制更新NameNode的元数据; 518 | 循环写入剩余的Blocks; 519 | 3.4 基础使用 520 | 521 | 格式化: 522 | 523 | hadoop namenode -format 524 | 基本命令: 525 | 526 | # 打印文件 527 | hadoop fs -ls [path] 528 | 529 | # 建立目录 530 | hadoop fs -mkdir [dir_name] 531 | 532 | # 上传文件 533 | hadoop fs -pu [filename] 534 | 535 | # 查看文件 536 | hadoop fs -cat [filename] 537 | 538 | # 下载文件 539 | hadoop fs -get [src_name] [dis_name] 540 | 541 | # 文件系统使用报告 542 | hadoop dfsadmin -report 543 | 4. MapReduce 并行计算框架 544 | 545 | 4.1 基本原理 546 | 547 | 分而治之原理,将一个大任务分解成多个小任务(Map),并行执行后再合并结果(Reduce); 548 | MR举例 549 | 550 | 切分任务; 551 | 分别统计; 552 | 组合规约; 553 | 汇总统计; 554 | 例如统计100G的日志文件中,出现次数最多的IP地址,可以分为以下步骤: 555 | 556 | 日志文件按照时间区段进行分解到不同的任务节点上(Map); 557 | 任务节点分别统计各个IP地址出现的次数; 558 | 任务节点将统计结果,根据一定规则汇总规约(Reduce); 559 | 最终产生排序结果; 560 | 561 | 4.2 运行流程 562 | 563 | 4.2.1 组成部分 564 | 565 | Job - 整体的作业; 566 | Task - 任务,一个Job由多个Task组成; 567 | MapTask 568 | ReduceTask 569 | JobTracker - 管理节点,负责分解Map任务和Reduce任务; 570 | TaskTracker - 任务处理节点,负责处理任务; 571 | MapTaskTracker 572 | ReduceTaskTracker 573 | 4.2.2 JobTracker 574 | 575 | 作业调度; 576 | 任务分配、监控任务执行进度; 577 | 监控TaskTracker的状态; 578 | 4.2.3 TaskTracker 579 | 580 | 执行任务; 581 | 汇报任务状态; 582 | 4.2.4 执行过程 583 | 584 | MR执行过程 585 | 586 | 任务提交到JboTracker; 587 | 数据分片; 588 | Map端分配Map任务,由MapTaskTracker处理; 589 | 产生中间结果KEY-VALUE对; 590 | Reduce端分配Reudce任务,由ReduceTaskTracker处理; 591 | 写回结果的HSFS; 592 | 4.3 容错机制 593 | 594 | 重复执行:重复执行过任务4次后放弃; 595 | 推测执行:某个节点计算速度异常时,另外找一个节点负责处理; 596 | 4629 597 | fsneak 598 | 退出账号 599 | 当前文档 600 | 恢复至上次同步状态 601 | 删除文档 602 | 导出... 603 | 预览文档 604 | 分享链接 605 | 系统 606 | 设置 607 | 下载桌面客户端 608 | 下载离线Chrome App 609 | 使用说明 610 | 快捷帮助 611 | 常见问题 612 | 关于 613 | 614 | 搜索文件 615 | 01. 写字台 Hadoop 大数据平台 - 学习笔记 616 | 01. 写字台 JavaScript 面向对象 - 学习笔记 617 | 02. 计划 2016年工作/生活月度总结 618 | 01. 写字台 Lucene - 学习笔记 619 | 归档 620 | B1. 资源管理 621 | 02. Java 622 | C1. IT网管 623 | 01. Web 624 | B3. 监控管理 625 | 04. Linux 626 | 01. 写字台 627 | 05. Other 628 | B4. 运维管理 629 | 02. 计划 630 | B2. 综合门户 631 | 08. Reading 632 | 633 | -------------------------------------------------------------------------------- /doc/python/README.md: -------------------------------------------------------------------------------- 1 | #Python - 学习笔记 2 | 3 | ## 1. 简介 4 | 适合的领域: 5 | - Web网站和各种网络服务; 6 | - 系统工具和脚本; 7 | - 作为胶水预言把其他语言开发模块包装起来方便使用; 8 | - 跨平台; 9 | 10 | 不适合的领域: 11 | - 贴近硬件的代码; 12 | - 移动开发; 13 | - 游戏开发; 14 | 15 | 16 | 缺点: 17 | - 不能加密; 18 | - 运行速度慢; 19 | 20 | 版本: 21 | - `2.7`:第三方库较多; 22 | - `3.3` :语法和2.7版本不兼容; 23 | 24 | ## 2. 变量和数据类型 25 | ### 2.1 基本数据类型 26 | - 整数:`1`, `100`, `-100`; 27 | - 浮点数:`1.2`, `3.14`, `1.23e9`; 28 | - 字符串:`'str'`,`"abcd"`; 29 | - 空值:`None`; 30 | - 布尔值:`False`,`True`,`and`,`or`,`not`; 31 | 32 | ### 2.2 注释 33 | 注释用`#`作为开头: 34 | ``` python 35 | # 这是一些注释 36 | # print 'hello world' 37 | ``` 38 | 39 | ### 2.3 变量 40 | - 变量名必须是大小写英文、数字和下划线(_)的组合,且不能用数字开头。 41 | - 变量本身的类型是不固定的,是一种动态语言; 42 | ``` python 43 | a = 123 # a是整数 44 | print a 45 | a = 'imooc' # a变为字符串 46 | print a 47 | ``` 48 | 49 | ### 2.4 字符串 50 | - 单引号或双引号包围的文本为字符串; 51 | - 特殊字符需要使用转义符号; 52 | - 在字符串前加前缀`r`表示`raw`字符串,里面的字符都不需要转义了; 53 | - 在字符串前加前缀`u`表示`unicode`字符串,支持中文等编码; 54 | - 可以用`'''str'''`表示多行字符串; 55 | - 可以用`# -*- coding: utf-8 -*-`指定字符`UTF-8`,以便支持中文;必须写在文件的第一行; 56 | - 可以用`str[index]`访问字符串的某一个字符; 57 | - 可以用`str[start:end:step]`对字符串进行切片; 58 | ``` python 59 | # 指定字符编码 60 | # -*- coding: utf-8 -*- 61 | # 基本字符串 62 | str = 'Learn "Python" in imooc' 63 | # raw字符串 64 | str = 'Line 1\nLine 2\nLine 3' 65 | # 多行字符串 66 | str = '''Line 1 67 | Line 2 68 | Line 3''' 69 | ``` 70 | 71 | ### 2.5 整数和浮点数 72 | - 支持基本的四则运算; 73 | - 有小数点的数字为浮点数; 74 | - 整数之间的计算结果为整数,整数和浮点数的运算结果为浮点数; 75 | ``` python 76 | 1 + 2 # ==> 整数 3 77 | 1.0 + 2.0 # ==> 浮点数 3.0 78 | ``` 79 | 80 | ### 2.6 布尔类型 81 | - 只有`True`和`False`两个取值; 82 | - `0`,`空字符串`,`None`当做`False`看待; 83 | - 短路计算; 84 | ``` python 85 | a = True 86 | print a and 'a=T' or 'a=F' # ==> a=T 87 | ``` 88 | ## 3. 集合 89 | ### 3.1 list 90 | - 定义列表 91 | - `list`是一种有序集合,可以新增,删除元素; 92 | - 使用`[ ]`可以定义一个`list`对象; 93 | - `list`中的元素不要求是相同的数据类型; 94 | - 访问列表 95 | - 可以使用下表索引访问列表`list[1]`,索引从0开始,注意不要越界; 96 | - 可以使用负数的`倒序索引`访问列表`list[-1]`,即为倒数第一个元素; 97 | - `len(list)`可以计算列表的长度; 98 | - 切片 99 | - `L[m:n]`:索引m到n的元素,不包括n; 100 | - `L[:]`全部元素; 101 | - `L[:n]`小于n的元素; 102 | - `L[m:]`大于m的元素; 103 | - `L[m:n:x]`:从m开始,每x个元素取一个数,直到n; 104 | - 倒序切片,第一个元素是`-1`; 105 | - 操作列表 106 | - 使用`append(e)`在列表的尾部加入元素; 107 | - 使用`insert(index,e)`在列表中加入元素; 108 | - 使用`pop()`方法可以删掉`list`的最后一个元素,并返回最后一个元素; 109 | - 使用`pop(index)`方法可以删掉指定下标的元素; 110 | - 列表生成 111 | - `[x * x for x in range(1, 11)]`:生成列表,不包括最后一个元素; 112 | - `[generate_tr(name, score) for name, score in d.iteritems()]`:生成表达式可以是函数; 113 | - `[ x.upper() for x in L if isinstance(x, str)]`:可以加条件判断过滤; 114 | ``` python 115 | # 定义list 116 | L = ['Adam', 95.5, 'Lisa', 85, 'Bart', 59] 117 | # 下标访问 118 | print L[0] 119 | print L[-1] 120 | # 操作元素 121 | L.insert(2, 'Paul') 122 | L.append('Jack') 123 | L.pop() 124 | ``` 125 | 126 | ### 3.2 tuple 127 | - `tuple`为只读的列表,一旦创建就不能修改了; 128 | - `tuple`使用`( )`进行定义; 129 | - 使用`t[1]`访问元组的元素; 130 | - 定义单元数元组需要多加一个逗号`(0, )` 131 | ```python 132 | # 定义tuple 133 | t = (0,1, 2, 3, 4, 5, 6, 7, 8, 9) 134 | 135 | # 单元素元组 136 | t = (0, ) 137 | ``` 138 | 139 | ### 3.3 dict 140 | - `dict`就是哈希表,使用花括号`{ key:value,key:value}`语法定义; 141 | - 使用`dict[key]`访问`dict`的元素,`key`不存在会报错; 142 | - 使用`dict.get(key)`访问`dict`元素,`key`不存在会返回`None`; 143 | - 使用`dict.pop(key)`返回并删除一个元素; 144 | - 可以使用`for key in dict`遍历`dict`; 145 | - 可以使用`for key, value in dict.itmes()`遍历`dict`; 146 | - 可以使用`for k, v in kwargs.iteritems()`遍历`dict`; 147 | - `dict.values() `获取值的列表; 148 | - 149 | 150 | ``` python 151 | # 定义dict 152 | d = { 153 | 'Adam': 95, 154 | 'Lisa': 85, 155 | 'Bart': 59 156 | } 157 | # 访问dict 158 | d.get('Adam') 159 | d['Lisa'] 160 | # 判断key是否存在 161 | 'Adam' in d 162 | # 遍历dict 163 | for k in d: 164 | print k, d[k] 165 | # 遍历dict 166 | for k, v in d.items(): 167 | print k, v 168 | ``` 169 | 170 | ### 3.4 set 171 | - `set`和`list`类似,但是`set`是无序的,且元素不能重复; 172 | - 使用`set(list)`定义一个`set`; 173 | - 使用`s.remove(item)`删除一个元素; 174 | - 使用`s.add(item)`加入一个元素; 175 | - 访问`set`的元素,其实就是判断元素是否在`set`中; 176 | - 可以使用`for key in set`遍历`set` 177 | 178 | ``` python 179 | # 定义 180 | s = set(['A', 'B', 'C']) 181 | # 访问 182 | 'A' in set 183 | # 遍历 184 | 185 | ``` 186 | 187 | ## 4. 条件判断和循环 188 | ### 4.1 if 189 | >缩进规则:相同缩进的代码为代码块;4个空格; 190 | 191 | - `if`语句后为布尔表达式,用`:`表示代码块开始; 192 | - 可以使用`if-elif-else`格式; 193 | - 可以使用表达式形式`c = a if a>b else b`; 194 | ``` python 195 | if score >= 90: 196 | print 'excellent' 197 | elif score >= 80: 198 | print 'good' 199 | elif score >=60: 200 | print 'passed' 201 | else: 202 | print 'failed' 203 | 204 | # 单行形式 205 | (t2 - t1) * 1000 if unit=='ms' else (t2 - t1) 206 | ``` 207 | 208 | ### 4.2 for 循环 209 | - 可以采用`for in`关键词遍历列表或元组; 210 | - 可以使用`break`退出循环;`continue`继续循环; 211 | ``` python 212 | L = [75, 92, 59, 68] 213 | sum = 0.0 214 | for v in L: 215 | sum += v 216 | print sum / 4 217 | ``` 218 | 219 | ### 4.3 while 循环 220 | - 和其他语言一样,根据布尔表达式判断是否继续循环; 221 | - 可以使用`break`退出循环;`continue`继续循环; 222 | ``` python 223 | while x <= 100: 224 | sum += x 225 | x += 1 226 | print sum 227 | ``` 228 | 229 | ## 5. 函数 230 | ### 5.1 常用函数 231 | ####5.1.1 内置函数: 232 | - `cmp(x, y)`:比较函数; 233 | - `int()`:转换为整数; 234 | - `float()`:转换为浮点数; 235 | - `str()`:转换为字符串; 236 | - `len()`:求集合长度; 237 | - `zip(seq1,seq2)`:将两个集合合并成一个,每个元素是一个元组; 238 | - `range(start,top,setp)`:创建序列; 239 | - `enumerate(iterable)`:将集合的每个元素变成有序号的元组; 240 | - `isinstance(x, str)`:判断变量的类型; 241 | 242 | #### 5.1.2 math 243 | - `math.sqrt(x)`:平方根; 244 | 245 | #### 5.1.3 str 246 | 可以在`str`上调用也可以直接在字符串上调用; 247 | - `lower(s)` 248 | - `upper(s)` 249 | - `strip(s, chars)`:前后去除指定字符; 250 | 251 | #### 5.1.4 time 252 | - `time()`:当前时间; 253 | 254 | ### 5.1.5 os.path 255 | - `isdir()` 256 | - `isfile()` 257 | 258 | ### 5.2 定义函数 259 | - 使用`def`关键词定义一个函数,依次写出函数名、参数、冒号; 260 | - 使用`retutn`语句进行返回; 261 | - 可以返回多值`return x, y`,实际上是一个`tuple`; 262 | - 可以定义默认参数`def fun(x=0)`,默认参数只能定义在必须参数后面; 263 | - 可以定义可变参数`def fun(*args)`,实际上就是传入一个`tuple`; 264 | 265 | ``` 266 | # 定义函数 267 | def square_of_sum(L): 268 | sum = 0 269 | for i in L: 270 | sum += i * i 271 | return sum 272 | # 返回多值 273 | def swap(a, b): 274 | return b, a 275 | x, y = swap(1, 10) 276 | # 默认参数 277 | def incr(v=0): 278 | v += 1 279 | return v 280 | ``` 281 | 282 | ## 6. 函数式编程 283 | ### 6.1 特点 284 | - 把计算视为函数而非指令; 285 | - 纯函数式编程:不需要变量,没有副作用,测试简单; 286 | - 支持高阶函数,函数可以作为变量传入,代码简洁; 287 | - 支持闭包,能够返回函数; 288 | - 有限度的支持匿名函数; 289 | 290 | ### 6.2 高阶函数 291 | - 变量可以指向函数,可以对变量进行调用; 292 | - 函数名其实就是指向函数的变量; 293 | - 高阶函数:能够接受函数作为参数的函数; 294 | - 函数可以作为返回值; 295 | ``` python 296 | def fun(x, y, f): 297 | return f(x) + f(y) 298 | # 将abs函数作为参数传入 299 | print fun(1, -2, abs) 300 | ``` 301 | 302 | ### 6.3 内置高阶函数 303 | - `map(function, sequence)`:将函数作用于每个对象,得到一个新的集合; 304 | - `reduce(function sequence)`:对list的每个元素反复调用函数f,并返回最终结果值; 305 | - `fliter(function, sequence)`:对于list的每个元素,检查其是否满足函数f,返回满足的元素list; 306 | - `sorted(iterable, cmp)`:自定义排序; 307 | 308 | ### 6.4 闭包 309 | - 内层函数**引用了外层函数的变量**(参数也算变量),然后返回内层函数的情况,称为闭包(`Closure`); 310 | - 要正确使用闭包,就要**确保引用的局部变量在函数返回后不能变**; 311 | 312 | ``` python 313 | # 高阶函数与闭包 314 | def count(): 315 | fs = [] 316 | for i in range(1, 4): 317 | def g(x): 318 | def f(): 319 | v = x 320 | return v * v 321 | return f 322 | fs.append(g(i)) 323 | return fs 324 | f1, f2, f3 = count() 325 | print f1(), f2(), f3() # 1, 4, 9 326 | ``` 327 | 328 | ### 6.5 匿名函数 329 | - 匿名函数 `lambda x: x * x` 330 | - 关键字`lambda` 表示匿名函数,冒号前面的 x 表示函数参数; 331 | - 匿名函数只能有一个表达式,不写return; 332 | - 返回函数的时候,也可以返回匿名函数; 333 | 334 | ### 6.6 装饰器 335 | - 定义了一个函数,需要在代码运行时增强其功能,又不希望修改其代码; 336 | - `Python`的 `decorator` 本质上就是一个高阶函数,它接收一个函数作为参数,然后,返回一个新函数; 337 | - `Python`中的`@`语法就是为了简化装饰器的调用; 338 | - 可以将通用的切面功能抽取出来,避免重复编写代码; 339 | - `@log` 340 | - `@performance` 341 | - `@transaction` 342 | - 可以定义带参数的装饰器,需要再包装一层; 343 | - 可以使用`@functools.wraps(f)`,可以将原函数的所有必要属性都一个一个复制到新函数上; 344 | 345 | ``` python 346 | def performance(unit): 347 | def fn_wrapper(f): 348 | @functools.wraps(f) 349 | def fn(*args, **kwargs): 350 | start = time.time() 351 | result = f(*args, **kwargs) 352 | end = time.time() 353 | interval = end - start 354 | print 'call ' + f.__name__ + ' use ' + str(interval) + unit 355 | return result 356 | return fn 357 | return fn_wrapper 358 | 359 | @performance('sss') 360 | def factorial(n): 361 | return reduce(lambda x, y: x*y, range(1, n+1)) 362 | ``` 363 | 364 | ### 6.7 偏函数 365 | - 偏函数即为把一个参数多的函数变成一个参数少的新函数; 366 | - `functools.partial`就是帮助我们创建一个偏函数; 367 | 368 | ``` python 369 | # 创建了一个内置函数sorted的偏函数 370 | cmp_ignore_case = functools.partial(sorted, cmp=lambda x, y: cmp(x.upper(), y.upper())) 371 | ``` 372 | 373 | ## 7. 模块和包 374 | - 所有代码放到一个py文件中,无法维护; 375 | - 如果将代码拆分到多个py文件中,同一个名字的变量可以互补影响; 376 | - 模块的名称即为`py`文件的名称;包就是文件夹,且可以有多级; 377 | - 包下面必须有一个`__init__.py`; 378 | - 需要引用模块时,使用`import`命令导入需要使用的模块; 379 | - 同名的模块可以放到不同的包中,完整的模块名不冲突即可; 380 | 381 | 常用模块 382 | - `math` 383 | - `time` 384 | - `os` 385 | - `json` 386 | 387 | ### 7.1 导入模块 388 | - 使用`import`可以导入其他模块; 389 | - 使用`from .. import ...`可以导入模块下指定的函数; 390 | - 使用`as`可以在导入指定函数时进行重命名; 391 | - 可以使用`try: except:`语法进行动态导入; 392 | - 当新版本的一个特性与旧版本不兼容时,该特性将会在旧版本中添加到`__future__`中; 393 | 394 | ``` python 395 | # 导入模块 396 | import math 397 | # 导入函数 398 | from math import pow, sin, log 399 | # 别名 400 | from logging import log as logger 401 | # 动态导入 402 | try: 403 | import json 404 | except ImportError: 405 | import simplejson as json 406 | # 新特性 407 | from __future__ import unicode_literals 408 | ``` 409 | 410 | ### 7.2 安装第三方模块 411 | 基本方式: 412 | - `easy_install` 413 | - `pip` - 官方推荐的安装方式; 414 | 415 | 416 | ## 8. 面向对象 417 | ### 8.1 类与实例 418 | - 通过`class`关键字定义类; 419 | - 通过`类名()`创建类的实例; 420 | 421 | ``` python 422 | # 定义一个类 423 | class Person(object): 424 | pass 425 | # 创建实例 426 | p1 = Person() 427 | ``` 428 | ### 8.2 实例属性 429 | - **动态实例属性**:`Python`是动态语言,对每一个实例,都可以直接给他们的属性赋值; 430 | - **初始化实例属性**:可以使用`__init__()`方法,该方法在实例被创建时自动调用; 431 | - 相当于构造函数;在创建实例时,需要提供相对应的参数; 432 | - 第一个参数`self`默认传入自身的引用; 433 | - 可以使用`**kwargs`在最后一个参数传入`dict`参数; 434 | - 可以使用`setattr(object, name, value)`设置属性的值; 435 | - 如果一个属性由双下划线开头(`__`),该属性就无法被外部访问 436 | - `__xxx__`的属性时python中的特殊属性,可以被外部访问; 437 | - 按照习惯,单下划线开头的属性也不应该被外部访问; 438 | 439 | ``` python 440 | class Person(object): 441 | def __init__(self, name, birth, gender, **kwargs): 442 | self.name = name 443 | self.birth = birth 444 | self.gender = gender 445 | self.__score = 123; 446 | for k, v in kwargs.iteritems(): 447 | setattr(self, k, v) 448 | ``` 449 | 450 | ### 8.3 类属性 451 | > 绑定在一个实例上的属性不会影响其他实例,如果在类上绑定一个属性,则所有实例都可以访问类的属性。实例属性每个实例各自拥有,互相独立,而类属性有且只有一份;相当于**静态成员变量**。 452 | - 可以在类中直接定义类属性,相当于定义了一个静态成员变量; 453 | - 使用类属性时,可以通过类名直接访问,如`Person.count`; 454 | - 类属性也可以通过实例访问,但是当实例属性和类属性重名时,实例属性优先级高,它将屏蔽掉对类属性的访问; 455 | - `object`类是所有类的父类; 456 | - Python pass是空语句,是为了保持程序结构的完整性,pass 不做任何事情,一般用做占位语句。 457 | 458 | ``` python 459 | class Person(object): 460 | count = 0 461 | def __init__(self, name): 462 | Person.count += 1 463 | self.name = name 464 | 465 | p1 = Person('Bob') 466 | print Person.count 467 | p2 = Person('Alice') 468 | print Person.count 469 | p3 = Person('Tim') 470 | print Person.count 471 | 472 | ``` 473 | 474 | ### 8.4 实例方法 475 | - 实例的方法就是在类中定义的函数,它的第一个参数永远是 self,指向调用该方法的实例本身,其他参数和一个普通函数一样; 476 | - 使用`def`关键词定义实例方法; 477 | - 在 `class` 中定义的实例方法其实也是属性,它实际上是一个函数对象; 478 | - 函数和方法的区别: 479 | - 方法:类内普通方法,类方法; 480 | - 函数:普通函数,类内的静态方法; 481 | 482 | ```python 483 | class Person(object): 484 | def __init__(self, name): 485 | self.__name = name 486 | def get_name(self): 487 | return self.__name 488 | ``` 489 | 490 | ### 8.5 类方法 491 | - 通过标记一个 `@classmethod`,该方法将绑定到类上,而非类的实例; 492 | - 类方法的第一个参数将传入类本身,通常将参数名命名为 `cls`; 493 | - 因为是在类上调用,而非实例上调用,因此类方法无法获得任何实例变量,只能获得类的引用; 494 | 495 | ``` python 496 | class Person(object): 497 | __count = 0 498 | @classmethod 499 | def how_many(cls): 500 | return cls.__count 501 | 502 | def __init__(self, name): 503 | self.name = name 504 | Person.__count += 1 505 | ``` 506 | 507 | ## 9. 继承 508 | ### 9.1 继承一个类 509 | - 父类需要在类定义中指定`class chile(Parent)`; 510 | - 需要在`__init__`方法中显示调用父类的构造方法初始化父类属性`super(Child, self).__init__()`; 511 | - 也可在`__init__`方法中使用`Person.__init__(self)`初始化父类属性; 512 | - 可以使用`isinstance(p_object, class_or_type_or_tuple)`方法判断对象是否为某类型; 513 | 514 | ``` python 515 | class Person(object): 516 | def __init__(self, name, gender): 517 | self.name = name 518 | self.gender = name 519 | class Teacher(Person): 520 | def __init__(self, name, gender, course): 521 | Person.__init__(self, name, gender) 522 | self.course = course 523 | ``` 524 | 525 | ### 9.2 多态 526 | - 类具有继承关系,并且子类类型可以向上转型看做父类类型; 527 | - 调用方法时,先查找它自身的定义,如果没有定义,则顺着继承链向上查找,直到在某个父类中找到为止; 528 | - 动态语言和静态语言(例如Java)最大的差别之一。动态语言调用实例方法,不检查类型,只要方法存在,参数正确,就可以调用; 529 | 530 | ### 9.3 多重继承 531 | - 继承自多个父类时可以使用逗号分隔`class chile(Parent1, Parent2)`; 532 | - 需要分别调用两个父类的构造方法`Parent.__init__(self)`; 533 | 534 | ``` python 535 | class C(A, B) 536 | def __init__(self, a, b): 537 | A.__init__(self, a) 538 | B.__init__(self, b) 539 | ``` 540 | 541 | ### 9.4 获取对象信息 542 | - `isinstance()`:判断是否是某种类型的实例; 543 | - `type()`:返回一个`Type`对象,即为变量的类型; 544 | - `dir()`:获取变量所有的属性; 545 | - `getattr(obj, attr)`:获取对象的某个属性; 546 | - `setattr(obj, attr, value)`:设置对象的某个属性; 547 | 548 | ``` python 549 | class Person(object): 550 | def __init__(self, name, gender, **kw): 551 | self.name = name 552 | self.gender = gender 553 | for k, v in kw.iteritems(): 554 | setattr(self, k, v) 555 | ``` 556 | 557 | 558 | ## 10. 定制类 559 | ### 10.1 特殊方法 560 | - 特殊方法定义在`class`中; 561 | - 不需要直接调用; 562 | - `Python`的某些函数或操作符会调用对应的特殊方法; 563 | - 只需要编写用到的特殊方法; 564 | - 有关联性的特殊方法必须要同时实现; 565 | 566 | ### 10.2 常见特殊方法 567 | #### 10.2.1 `__str__`和`__repr__` 568 | - 如果要把一个类的实例变成 `str`,就需要实现特殊方法`__str__()`; 569 | - Python 定义了`__str__()`和`__repr__()`两种方法,`__str__()`用于显示给用户,而`__repr__()`用于显示给开发人员; 570 | 571 | ``` python 572 | class Student(Person): 573 | def __init__(self, name, gender, score): 574 | super(Student, self).__init__(name, gender) 575 | self.score = score 576 | def __str__(self): 577 | return '(Student: %s, %s, %s)' % (self.name, self.gender, self.score) 578 | __repr__ = __str__ 579 | ``` 580 | 581 | #### 10.2.2 `__cmp__` 582 | - 对 int、str 等内置数据类型排序时,Python的 sorted() 按照默认的比较函数 cmp 排序; 583 | - 如果对一组 `Student` 类的实例排序时,就必须提供我们自己的特殊方法 `__cmp__()`; 584 | 585 | ``` python 586 | def __cmp__(self, s): 587 | if self.score == s.score: 588 | return cmp(self.name, s.name) 589 | return -cmp(self.score, s.score) 590 | ``` 591 | 592 | #### 10.2.3 `__len__` 593 | - 一个类表现得像一个`list`,要获取有多少个元素,就得用 `len()` 函数; 594 | - 要让 `len()` 函数工作正常,类必须提供一个特殊方法`__len__()`,它返回元素的个数; 595 | 596 | ``` python 597 | def __len__(self): 598 | return len(self.numbers) 599 | ``` 600 | 601 | #### 10.2.4 数学运算符 602 | - `__add__` 603 | - `__sub__` 604 | - `__mul__` 605 | - `__div__` 606 | 607 | #### 10.2.5 类型转换 608 | 结果转为 int 或 float 609 | - `__int__` 610 | - `__float__` 611 | ``` python 612 | def __int__(self): 613 | return self.p // self.q 614 | 615 | def __float__(self): 616 | return float(self.p) / self.q 617 | ``` 618 | 619 | #### 10.2.6 @property 620 | - `@property`:可以将方法当做属性来调用; 621 | - `@attrName.setter`:将方法当做属性来用赋值; 622 | ``` python 623 | class Student(object): 624 | def __init__(self, name, score): 625 | self.name = name 626 | self.__score = score 627 | @property 628 | def score(self): 629 | return self.__score 630 | @score.setter 631 | def score(self, score): 632 | if score < 0 or score > 100: 633 | raise ValueError('invalid score') 634 | self.__score = score 635 | @property 636 | def grade(self): 637 | if self.score < 60: 638 | return 'C' 639 | if self.score < 80: 640 | return 'B' 641 | return 'A' 642 | s = Student('Bob', 59) 643 | print s.grade 644 | s.score = 60 645 | print s.grade 646 | s.score = 99 647 | print s.grade 648 | ``` 649 | 650 | #### 10.2.7 `__slots__` 651 | - `__slots__`是指一个类允许的属性列表; 652 | - `__slots__`的目的是限制当前类所能拥有的属性,如果不需要添加任意动态的属性,使用`__slots__`也能节省内存; 653 | 654 | ``` python 655 | class Person(object): 656 | __slots__ = ('name', 'gender') 657 | def __init__(self, name, gender): 658 | self.name = name 659 | self.gender = gender 660 | ``` 661 | 662 | 663 | #### 10.2.8 `__call__` 664 | - 在Python中,函数其实是一个对象; 665 | - 一个类实例也可以变成一个可调用对象,只需要实现一个特殊方法`__call__()`; 666 | 667 | ## 其他 668 | ### 异常处理 669 | ``` python 670 | try: 671 | print p.name 672 | print p.__score 673 | except AttributeError: 674 | print 'attributeerror' 675 | ``` 676 | ### 格式化输出 677 | ``` 678 | print '(Student: %s, %s, %s)' % (self.name, self.gender, self.score) 679 | ``` --------------------------------------------------------------------------------